简体   繁体   中英

AES Encryption I am trying to encrypt using AES encryption

I just want to migrate the ruby code to Java

here is my ruby code

require 'openssl'
require 'base64'

key = '7c54367a45b37a192abc2cd7f45203042350406f8'
cipher = OpenSSL::Cipher::Cipher.new('aes-128-ecb')
cipher.encrypt()


cipher = OpenSSL::Cipher::Cipher.new('aes-256-ecb')
cipher.encrypt()
cipher.key = key

crypt = cipher.update('Rahul')
crypt << cipher.final()

puts (Base64.encode64(crypt))

Here is what i am trying in Java

String getDecodedString(String key,String encodedValue,SupportedEncryptionAlgorithm algoInfo) 
{
    Cipher cipher = getCipherInstancenew(algoInfo, key,Cipher.DECRYPT_MODE);
    try
    {
        byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(encodedValue);

        int ctLength = cipher.getOutputSize(dec.length);
        byte[] plainText = new byte[cipher.getOutputSize(ctLength)];

        int ptLength = cipher.update(dec, 0, ctLength, plainText, 0);
        ptLength += cipher.doFinal(plainText, ptLength);

        return null; 
    }
    catch (IllegalBlockSizeException e)
    {
        LoggerFactory.getLogger(EncryptionHelper.class).error("Security Alert",e);
    }
    catch (BadPaddingException e)
    {
        LoggerFactory.getLogger(EncryptionHelper.class).error("Security Alert",e);
    }
    return null;
}

public static byte[] stringToBytes(String s) {
    byte[] b2 = new BigInteger(s, 36).toByteArray();
    return Arrays.copyOfRange(b2, 1, b2.length);
}

public static Cipher getCipherInstancenew(SupportedEncryptionAlgorithm algoInfo,String keyString,int mode) throws IOException
{
    byte[] decodedBytes;
    Cipher cipher=null;      
    try
    {
        decodedBytes = getBase64FromHEX(keyString).getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(decodedBytes, "AES");
        Security.addProvider(new BouncyCastleProvider());   
        cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
        cipher.init(mode, skeySpec );
    }
    catch (java.security.GeneralSecurityException e)
    {
        /*Strictly no logging as it is security class 
         *  There seems to be some issue with the Keys so alert it */
         //LoggerFactory.getLogger(EncryptionHelper.class).error("Security Alert",e);
         throw new IOException("GetCipherInstance does not exsists");
    }

    return cipher;

}

public static String getBase64FromHEX(String input) {

    byte barr[] = new byte[16];
    int bcnt = 0;
    for (int i = 0; i < 32; i += 2) {
        char c1 = input.charAt(i);
        char c2 = input.charAt(i + 1);
        int i1 = intFromChar(c1);
        int i2 = intFromChar(c2);

        barr[bcnt] = 0;
        barr[bcnt] |= (byte) ((i1 & 0x0F) << 4);
        barr[bcnt] |= (byte) (i2 & 0x0F);
        bcnt++;
    }

    BASE64Encoder encoder = new BASE64Encoder();
    return encoder.encode(barr);
}

private static int intFromChar(char c) {
    char[] carr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

    char clower = Character.toLowerCase(c);
    for (int i = 0; i < carr.length; i++) {
        if (clower == carr[i]) {
            return i;
        }
    }

    return 0;
}

It works with 32 byte String but not with the 41 bytes in Java but in Ruby it works for any length greater than 32 byte Strange Please help

I doubt that your calls to String.getBytes() are doing what you need them to do.

The getBytes() method uses the platform's default character encoding to convert the characters of a String to a sequence of bytes. The default platform character encoding is something like UTF-8, US-ASCII, or ISO-8859-1. It's not base-64 or hexadecimal.

Most character encodings can't handle the random 8-bit values that are used in cryptographic operations. So, for example, you generally can't create a new String from the bytes that result from encryption. Many of the values will be replaced with or ?, depending on your encoding. And, even if it happens to work on your machine, the machine on the next desk could be configured differently, and will fail when trying to decode that character string.

If you need to convert between binary data and text, use an encoding like Base-64.

The below Java code outputs the exact same base 64 encoded result from encrypting as the Ruby code and successfully decrypts it:

final Cipher encryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
encryptCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec("7c54367a45b37a192abc2cd7f4520304".getBytes(), "AES"));
final byte[] encrypt = encryptCipher.doFinal("This is my text".getBytes());
System.out.println(new String(Base64.encode(encrypt)));

final Cipher decryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
decryptCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec("7c54367a45b37a192abc2cd7f4520304".getBytes(), "AES"));
final byte[] decrypt = decryptCipher.doFinal(encrypt);
System.out.println(new String(decrypt));

The Ruby OpenSSL API is apparently only using the first 32 bytes of the key, since the following value for key returns the same value as the 41 byte version:

key = '7c54367a45b37a192abc2cd7f4520304'

Also, I'm not sure why cipher is initialized twice in the Ruby code as it isn't necessary as far as I can tell.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM