Decrypt C# RIJNDAEL encoded text

后端 未结 1 1830
名媛妹妹
名媛妹妹 2021-01-01 07:56

I\'m implementing in Java the communication to a third party application. As part of the login process, the third party application is sending an encrypted string that I hav

相关标签:
1条回答
  • 2021-01-01 08:49

    You don't need the BouncyCastleProvider for this, as AES is already included in Java. However PKCS#7 padding is incorrectly indicated by "PKCS5Padding", so "AES/CBC/PKCS7Padding" cannot be indicated without Bouncy Castle.

    The default Unicode encoding of .NET is actually more compatible with UTF-16LE. Leave it to Microsoft to not keep to standard names (although they may have preceded it).

    The Java JCE is not really build around streaming as the C# classes are, so it is better to avoid streaming altogether.

    I've rewritten your sample code to show how to properly code this in Java (you'll need to be Java 7 compatible though). Don't shove exceptions under the table, turn them into AssertError or RuntimeExceptions.

    I've use the Bouncy Castle Base 64 decoder, as that one was the one available both for you and for me (but otherwise this is independent of Bouncy). Java 8 has a base 64 class included.


    So without further ado:

    import static java.nio.charset.StandardCharsets.UTF_16LE;
    
    import java.security.GeneralSecurityException;
    import java.util.Arrays;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.bouncycastle.util.encoders.Base64;
    
    public class AuthenticationStringDecrypter {
    
        private static final String AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5PADDING";
        private static final int KEY_SIZE = 256;
    
        public static void main(final String[] args) throws Exception {
            System.out.println(decryptAuthorizationString(
                    "c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY=", "GAT"));
        }
    
        private static String decryptAuthorizationString(final String authString,
                final String password) {
            try {
                // --- check if AES-256 is available
                if (Cipher.getMaxAllowedKeyLength(AES_CBC_PKCS5PADDING) < KEY_SIZE) {
                    throw new IllegalStateException("Unlimited crypto files not present in this JRE");
                }
    
                // --- create cipher
                final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING);
    
                // --- create the key and initial vector bytes
                final byte[] passwordEncoded = password.getBytes(UTF_16LE);
                final byte[] keyData = Arrays.copyOf(passwordEncoded, KEY_SIZE
                        / Byte.SIZE);
                final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize());
    
                // --- init cipher
                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyData, "AES"),
                        new IvParameterSpec(ivBytes));
    
                // --- decode & decrypt authentication string
                final byte[] authBytes = Base64.decode(authString);
                final byte[] decryptedData = cipher.doFinal(authBytes);
    
                // WARNING: may still decrypt to wrong string if
                // authString or password are incorrect - 
                // BadPaddingException may *not* be thrown
                return new String(decryptedData, UTF_16LE);
            } catch (BadPaddingException | IllegalBlockSizeException e) {
                // failure to authenticate
                return null;
            } catch (final GeneralSecurityException e) {
                throw new IllegalStateException(
                        "Algorithms or unlimited crypto files not available", e);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题