The main reason you might want to do this is if you have a portal-like application on WebSphere and want to link to other applications on different non-WebSphere servers. This is only useful if WebSphere is your main point of entry.
Here's how you do it:
- Export the LTPA encryption key to a file from WebSphere using the admin console. You provide a passphrase and a filename.
- Find the "com.ibm.websphere.ltpa.3DESKey" value in the exported file. This is the encrypted key.
- Base64 decode the above key and decrypt with 3DES, using the passphrase provided. The decrypted value is the actual key for decrypting LTPA tokens.
- Take the "LtpaToken" cookie, base64 decode it, and decrypt it with the key. The legacy LtpaToken cookie (which you can get with "interoperability mode") is encrypted with 3DES; the newer LtpaToken2 cookie uses AES.
- Convert to String and parse. The string looks like "values%expiration%signature" where the expiration is a standard UNIX timestamp, which you should use to ensure the token is still valid; and the values somewhere will contain the user DN (e.g., uid=user,ou=company,dc=com).
The Alfresco codebase contains a good example of how to do this in Java
Relevant fragments of code:
private static final String AES_DECRIPTING_ALGORITHM = "AES/CBC/PKCS5Padding"; private static final String DES_DECRIPTING_ALGORITHM = "DESede/ECB/PKCS5Padding"; private byte[] getSecretKey(String ltpa3DESKey, String ltpaPassword) throws Exception { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(ltpaPassword.getBytes()); byte[] hash3DES = new byte[24]; System.arraycopy(md.digest(), 0, hash3DES, 0, 20); Arrays.fill(hash3DES, 20, 24, (byte) 0); final Cipher cipher = Cipher.getInstance(DES_DECRIPTING_ALGORITHM); final KeySpec keySpec = new DESedeKeySpec(hash3DES); final Key secretKey = SecretKeyFactory.getInstance("DESede").generateSecret(keySpec); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] secret = cipher.doFinal(Base64.decodeBase64(ltpa3DESKey.getBytes())); return secret; } private byte[] decrypt(byte[] token, byte[] key, String algorithm) throws Exception { SecretKey sKey = null; if (algorithm.indexOf("AES") != -1) { sKey = new SecretKeySpec(key, 0, 16, "AES"); } else { DESedeKeySpec kSpec = new DESedeKeySpec(key); SecretKeyFactory kFact = SecretKeyFactory.getInstance("DESede"); sKey = kFact.generateSecret(kSpec); } Cipher cipher = Cipher.getInstance(algorithm); if (algorithm.indexOf("ECB") == -1) { if (algorithm.indexOf("AES") != -1) { IvParameterSpec ivs16 = generateIvParameterSpec(key, 16); cipher.init(Cipher.DECRYPT_MODE, sKey, ivs16); } else { IvParameterSpec ivs8 = generateIvParameterSpec(key, 8); cipher.init(Cipher.DECRYPT_MODE, sKey, ivs8); } } else { cipher.init(Cipher.DECRYPT_MODE, sKey); } return cipher.doFinal(token); } private IvParameterSpec generateIvParameterSpec(byte key[], int size) { byte[] row = new byte[size]; for (int i = 0; i < size; i++) { row[i] = key[i]; } return new IvParameterSpec(row); } // How to use it: byte[] secretKey = getSecretKey(ltpa3DESKey, ltpaPassword); byte[] ltpaTokenBytes = Base64.decodeBase64(ltpaToken.getBytes()); String token = new String(decrypt(ltpaTokenBytes, secretKey, DES_DECRIPTING_ALGORITHM)); // or String token = new String(decrypt(ltpaTokenBytes, secretKey, AES_DECRIPTING_ALGORITHM));
No comments:
Post a Comment