2011-06-21 49 views
1

加密我只想Ruby代碼遷移到JavaAES加密我嘗試使用AES加密

這裏是我的Ruby代碼

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

小記:你真的不想使用ECB。不要試圖解釋爲什麼,只要看看維基百科上用ECB加密的圖片:https://secure.wikimedia.org/wikipedia/en/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29。請使用安全模式,例如CBC或CFB。 – Darhuuk

回答

2

的下面Java代碼從作爲Ruby代碼加密輸出完全相同的基64編碼的結果,成功地將其解密:

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

紅寶石OpenSSL的API顯然僅使用前32個字節的關鍵的,因爲對於key以下值返回相同的值41字節版本:

key = '7c54367a45b37a192abc2cd7f4520304' 

另外,我不知道爲什麼cipher在Ruby代碼初始化兩次,因爲它是沒有必要的,只要我能告訴。

+0

其實它是41位密鑰,紅寶石使用,這是我的主要問題我的意思是它是一個代碼將要加密它我仍然不確定它刪除截斷密鑰它看起來像一個十六進制字符串。所以我目前的狀態是我能夠生成密碼,但仍然試圖解密由Ruby生成的代碼 – Rahul

+0

Cipher getCipherInstancenew(String keyString,int mode)throws IOException byte [] decodedBytes; 密碼cipher = null; 嘗試 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) {} return cipher; } – Rahul

+0

String getDecodedString(String key,String encodedValue,SupportedEncryptionAlgorithm algoInfo)throws IOException,ShortBufferException { Cipher cipher = getCipherInstancenew(algoInfo,key,Cipher.DECRYPT_MODE); 嘗試 {int ctLength = cipher.getOutputSize(encodedValue.getBytes()。length); byte [] plainText = new byte [cipher.getOutputSize(ctLength)]; int ptLength = cipher.update(stringToBytes(encodedValue),0,ctLength,plainText,0); ptLength + = cipher.doFinal(plainText,ptLength); 返回null; – Rahul

2

我懷疑你打給String.getBytes()的電話正在做你需要他們做的事情。

getBytes()方法使用平臺的默認字符編碼將String的字符轉換爲字節序列。默認的平臺字符編碼類似UTF-8,US-ASCII或ISO-8859-1。它不是base-64或十六進制。

大多數字符編碼不能處理加密操作中使用的隨機8位值。因此,例如,您通常不能從加密產生的字節中創建新的String。根據您的編碼,許多值將被替換爲 或?。而且,即使它在您的機器上正常工作,下一個桌面上的機器也可能配置不同,並且在嘗試解碼該字符串時會失敗。

如果您需要在二進制數據和文本之間進行轉換,請使用像Base-64這樣的編碼。

+0

感謝您通過String.getBytes您的密鑰,因爲當我執行cipher.init(mode,skeySpec); 我得到無效的密鑰長度異常 – Rahul

+0

@Rahul - 是的,對於密鑰,但也是當你採取加密的結果(一個字節[]),並創建一個新的「字符串」(這實際上是相反的'getBytes()'操作)。這破壞了密文;你將無法解密它,因爲一些信息無法挽回地丟失。如果你需要文本,將字節轉換爲base-64之類的文本。 – erickson

+0

我也嘗試了密鑰對話,但不幸的是我得到了相同的錯誤 – Rahul