Apereo CAS Core Utilities - A comprehensive utility library providing functional programming constructs, encryption utilities, configuration helpers, and core infrastructure components for the Central Authentication Service framework
—
Comprehensive cryptographic utilities including cipher executors, password encoders, certificate management, and key handling for secure operations.
import org.apereo.cas.util.cipher.AbstractCipherExecutor;
import org.apereo.cas.util.crypto.CipherExecutor;
import org.apereo.cas.util.crypto.EncodableCipher;
import org.apereo.cas.util.crypto.DecodableCipher;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;Abstract base class providing common operations for signing and encrypting objects.
public abstract class AbstractCipherExecutor<T, R> implements CipherExecutor<T, R> {
// Key extraction utilities
public static PrivateKey extractPrivateKeyFromResource(String signingSecretKey);
public static PublicKey extractPublicKeyFromResource(String secretKeyToUse);
// Core operations (inherited from CipherExecutor interface)
@Override
public boolean isEnabled();
@Override
public Key getSigningKey();
@Override
public CipherExecutor<T, ?> withSigningDisabled();
// Encoding/Decoding operations (from EncodableCipher and DecodableCipher interfaces)
// Must be implemented by concrete subclasses
@Override
public T encode(R value, Object[] parameters);
@Override
public R decode(T value, Object[] parameters);
@Override
public T encode(R value);
@Override
public R decode(T value);
}Creating custom cipher executors:
public class TokenCipherExecutor extends AbstractCipherExecutor<String, String> {
public TokenCipherExecutor(String secretKey, String signingKey) {
setSecretKeyEncryption(secretKey);
setSigningKey(signingKey);
}
@Override
public String encode(String value, Object[] parameters) {
if (!isEnabled()) {
return value;
}
// Encrypt the value
String encrypted = encryptValue(value);
// Sign the encrypted value
return sign(encrypted);
}
@Override
public String decode(String value, Object[] parameters) {
if (!isEnabled()) {
return value;
}
// Verify signature first
if (!verifySignature(value, value)) {
throw new DecryptionException("Invalid signature");
}
// Extract and decrypt
String encrypted = extractEncryptedValue(value);
return decryptValue(encrypted);
}
}Key management:
// Extract keys from resources
PrivateKey privateKey = AbstractCipherExecutor.extractPrivateKeyFromResource("file:private.pem");
PublicKey publicKey = AbstractCipherExecutor.extractPublicKeyFromResource("classpath:public.pem");
// Use in cipher configuration
TokenCipherExecutor cipher = new TokenCipherExecutor();
cipher.setSigningKey(privateKey);
cipher.setEncryptionKey(publicKey);Default implementation for ticket encryption and signing.
public class DefaultTicketCipherExecutor extends BaseStringCipherExecutor {
public DefaultTicketCipherExecutor(String secretKeyEncryption,
String secretKeySigning,
String alg,
int signingKeySize,
int encryptionKeySize);
public DefaultTicketCipherExecutor(String secretKeyEncryption,
String secretKeySigning,
boolean enableEncryption,
boolean enableSigning,
int signingKeySize,
int encryptionKeySize);
}Jasypt-based number encryption for sensitive numeric data.
public class JasyptNumberCipherExecutor extends AbstractCipherExecutor<Number, Number> {
public JasyptNumberCipherExecutor(String secretKey, String algorithm);
@Override
public Number encode(Number value, Object[] parameters);
@Override
public Number decode(Number value, Object[] parameters);
}JWT-based string cipher using JSON Web Key Sets.
public class JsonWebKeySetStringCipherExecutor extends BaseStringCipherExecutor {
public JsonWebKeySetStringCipherExecutor(Resource jwksResource);
public JsonWebKeySetStringCipherExecutor(String jwksJson);
// Inherits encode/decode from BaseStringCipherExecutor
}RSA key pair cipher for asymmetric encryption operations.
public class RsaKeyPairCipherExecutor extends AbstractCipherExecutor<String, String> {
public RsaKeyPairCipherExecutor(PrivateKey privateKey, PublicKey publicKey);
public RsaKeyPairCipherExecutor(String privateKeyLocation, String publicKeyLocation);
@Override
public String encode(String value, Object[] parameters);
@Override
public String decode(String value, Object[] parameters);
}Ticket encryption:
// Configure ticket cipher
DefaultTicketCipherExecutor ticketCipher = new DefaultTicketCipherExecutor(
"encryption-secret-key-32-chars-min", // Encryption key
"signing-secret-key-64-chars-minimum", // Signing key
"AES", // Algorithm
512, // Signing key size
256 // Encryption key size
);
// Encrypt/decrypt tickets
String ticket = "TGT-123-example-ticket";
String encrypted = ticketCipher.encode(ticket);
String decrypted = ticketCipher.decode(encrypted);Number encryption:
// Jasypt number cipher
JasyptNumberCipherExecutor numberCipher = new JasyptNumberCipherExecutor(
"secret-key",
"PBEWithMD5AndTripleDES"
);
// Encrypt sensitive numbers
Long userId = 12345L;
Number encrypted = numberCipher.encode(userId);
Long decrypted = (Long) numberCipher.decode(encrypted);RSA asymmetric encryption:
// RSA cipher with key files
RsaKeyPairCipherExecutor rsaCipher = new RsaKeyPairCipherExecutor(
"file:/path/to/private.pem",
"file:/path/to/public.pem"
);
// Or with key objects
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();
RsaKeyPairCipherExecutor rsaCipher2 = new RsaKeyPairCipherExecutor(
keyPair.getPrivate(),
keyPair.getPublic()
);
// Encrypt/decrypt data
String sensitive = "confidential-data";
String encrypted = rsaCipher.encode(sensitive);
String decrypted = rsaCipher.decode(encrypted);Utility methods for cipher operations and key management.
@UtilityClass
public class CipherExecutorUtils {
// Key generation utilities
public static String generateSecretKey(int keySize);
public static Key generateKey(String algorithm, int keySize);
// Cipher configuration
public static CipherExecutor<String, String> newStringCipherExecutor(
String encryptionKey,
String signingKey
);
// Validation utilities
public static boolean isEnabled(CipherExecutor<?, ?> cipher);
public static void validateCipherConfiguration(CipherExecutor<?, ?> cipher);
}Basic implementation for identifiable cryptographic keys.
public class BasicIdentifiableKey implements IdentifiableKey {
private final String id;
private final Key key;
public BasicIdentifiableKey(String id, Key key);
@Override
public String getId();
@Override
public Key getKey();
@Override
public String getAlgorithm();
}Key management with identifiers:
// Create identifiable keys
SecretKey aesKey = generateAESKey();
BasicIdentifiableKey identifiableKey = new BasicIdentifiableKey("key-2024-01", aesKey);
// Use in key stores or rotation scenarios
Map<String, IdentifiableKey> keyStore = new HashMap<>();
keyStore.put(identifiableKey.getId(), identifiableKey);
// Retrieve by ID for cipher operations
IdentifiableKey currentKey = keyStore.get("key-2024-01");
CipherExecutor cipher = createCipherWithKey(currentKey.getKey());Certificate management utilities for X.509 operations.
@UtilityClass
public class CertUtils {
// Certificate reading
public static X509Certificate readCertificate(Resource resource);
public static X509Certificate readCertificate(InputStream inputStream);
public static X509Certificate readCertificate(String certificateString);
// Certificate validation
public static boolean isCertificateValid(X509Certificate cert);
public static boolean isCertificateValid(X509Certificate cert, Date validationDate);
// Certificate information extraction
public static String getSubjectDN(X509Certificate cert);
public static String getIssuerDN(X509Certificate cert);
public static Date getNotBefore(X509Certificate cert);
public static Date getNotAfter(X509Certificate cert);
}Certificate operations:
// Read certificates from various sources
Resource certResource = new ClassPathResource("server.crt");
X509Certificate cert = CertUtils.readCertificate(certResource);
// Validate certificates
boolean isValid = CertUtils.isCertificateValid(cert);
boolean isValidAtDate = CertUtils.isCertificateValid(cert, new Date());
// Extract certificate information
String subject = CertUtils.getSubjectDN(cert);
String issuer = CertUtils.getIssuerDN(cert);
Date expires = CertUtils.getNotAfter(cert);
// Use in SSL configuration
if (CertUtils.isCertificateValid(cert)) {
configureSSLContext(cert);
} else {
log.warn("Certificate expired: {}", CertUtils.getNotAfter(cert));
}Default password encoding implementation with configurable algorithms.
public class DefaultPasswordEncoder implements PasswordEncoder {
public DefaultPasswordEncoder(String encodingAlgorithm);
public DefaultPasswordEncoder(String encodingAlgorithm, String characterEncoding);
@Override
public String encode(CharSequence rawPassword);
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword);
}Glibc crypt-compatible password encoder for Unix-style password hashing.
public class GlibcCryptPasswordEncoder implements PasswordEncoder {
public GlibcCryptPasswordEncoder();
public GlibcCryptPasswordEncoder(String saltPrefix);
@Override
public String encode(CharSequence rawPassword);
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword);
}Password encoding:
// Default password encoder with SHA-256
DefaultPasswordEncoder encoder = new DefaultPasswordEncoder("SHA-256", "UTF-8");
String encoded = encoder.encode("user-password");
boolean matches = encoder.matches("user-password", encoded);
// Glibc crypt encoder for Unix compatibility
GlibcCryptPasswordEncoder cryptEncoder = new GlibcCryptPasswordEncoder("$6$"); // SHA-512
String crypted = cryptEncoder.encode("user-password");
boolean cryptMatches = cryptEncoder.matches("user-password", crypted);
// Use in authentication
@Service
public class AuthenticationService {
private final PasswordEncoder passwordEncoder = new DefaultPasswordEncoder("SHA-256");
public boolean authenticate(String username, String password) {
User user = userRepository.findByUsername(username);
return user != null && passwordEncoder.matches(password, user.getPasswordHash());
}
}Spring factory beans for key management in application contexts.
public class PrivateKeyFactoryBean implements FactoryBean<PrivateKey> {
public PrivateKeyFactoryBean(Resource location, String algorithm);
@Override
public PrivateKey getObject();
@Override
public Class<?> getObjectType();
@Override
public boolean isSingleton();
}public class PublicKeyFactoryBean implements FactoryBean<PublicKey> {
public PublicKeyFactoryBean(Resource location, String algorithm);
@Override
public PublicKey getObject();
@Override
public Class<?> getObjectType();
@Override
public boolean isSingleton();
}Spring configuration with key factory beans:
@Configuration
public class CryptoConfiguration {
@Bean
public PrivateKeyFactoryBean signingPrivateKey() {
return new PrivateKeyFactoryBean(
new ClassPathResource("signing-private.pem"),
"RSA"
);
}
@Bean
public PublicKeyFactoryBean signingPublicKey() {
return new PublicKeyFactoryBean(
new ClassPathResource("signing-public.pem"),
"RSA"
);
}
@Bean
public CipherExecutor<String, String> jwtCipher(
@Qualifier("signingPrivateKey") PrivateKey privateKey,
@Qualifier("signingPublicKey") PublicKey publicKey) {
return new RsaKeyPairCipherExecutor(privateKey, publicKey);
}
}Exception thrown during decryption failures.
public class DecryptionException extends RuntimeException {
public DecryptionException(String message);
public DecryptionException(String message, Throwable cause);
public DecryptionException(Throwable cause);
}Exception handling in cipher operations:
public class SecureDataService {
private final CipherExecutor<String, String> cipher;
public String processSecureData(String encryptedData) {
try {
return cipher.decode(encryptedData);
} catch (DecryptionException e) {
log.error("Failed to decrypt data", e);
throw new ServiceException("Invalid encrypted data", e);
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-apereo-cas--cas-server-core-util-api