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