AES加密我正在尝试使用AES加密进行加密

时间:2011-06-21 17:12:28

标签: java ruby encryption aes

我只想将ruby代码迁移到Java

这是我的红宝石代码

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))

以下是我在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;
}

它适用于32字节字符串,但不适用于Java中的41字节,但在Ruby中,它适用于大于32字节的任何长度。奇怪请帮助

2 个答案:

答案 0 :(得分:2)

我怀疑你打电话给String.getBytes()正在做你需要他们做的事。

getBytes()方法使用平台的默认字符编码将String的字符转换为字节序列。默认平台字符编码类似于UTF-8,US-ASCII或ISO-8859-1。它不是base-64或十六进制。

大多数字符编码无法处理加密操作中使用的随机8位值。因此,例如,您通常无法根据加密产生的字节创建新的String。许多值将替换为 或?,具体取决于您的编码。而且,即使它恰好在您的计算机上工作,下一个桌面上的计算机也可能配置不同,并且在尝试解码该字符串时会失败。

如果您需要在二进制数据和文本之间进行转换,请使用类似Base-64的编码。

答案 1 :(得分:2)

以下Java代码输出完全相同的base 64编码结果,加密为Ruby代码并成功解密:

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));

Ruby OpenSSL API显然只使用密钥的前32个字节,因为key的以下值返回与41字节版本相同的值:

key = '7c54367a45b37a192abc2cd7f4520304'

另外,我不确定为什么cipher在Ruby代码中被初始化两次,因为据我所知,这是不必要的。