Шифрование AES Я пытаюсь зашифровать с использованием шифрования AES - PullRequest
1 голос
/ 21 июня 2011

Я просто хочу перенести код 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-байтовой строкой, но не с 41 байтом в Java, но в Ruby он работает для любой длины, превышающей 32 байта. Странно Пожалуйста, помогите

Ответы [ 2 ]

2 голосов
/ 21 июня 2011

Приведенный ниже код Java выводит точно такой же результат, закодированный в кодировке 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, поскольку, насколько я могу судить, это необязательно.

2 голосов
/ 21 июня 2011

Я сомневаюсь, что ваши вызовы String.getBytes() делают то, что вам нужно.

Метод getBytes() использует кодировку символов по умолчанию платформы для преобразования символов String в последовательностьбайтов.Кодировка символов платформы по умолчанию - что-то вроде UTF-8, US-ASCII или ISO-8859-1.Это не base-64 или шестнадцатеричное.

Большинство кодировок символов не могут обрабатывать случайные 8-битные значения, которые используются в криптографических операциях.Так, например, вы обычно не можете создать новый String из байтов, которые являются результатом шифрования.Многие значения будут заменены на � или?, В зависимости от вашей кодировки.И даже если это работает на вашем компьютере, компьютер на следующем столе может быть настроен по-другому, и при попытке декодировать эту строку символов произойдет сбой.

Если вам нужно выполнить преобразование между двоичными данными и текстом, используйте кодировку как Base-64.

...