2015-08-14 15 views
4

我有我使用加密的javax.crypto.Cipher中的相同方式使用bash腳本加密的字符串。在java中,我使用帶有「」鍵的AES-256。但是,當我使用OpenSSL的,我不得不轉換 「」 爲十六進制,但結果是不一樣的java的Java那樣

echo "lun01" | openssl aes-256-cbc -e -a -K 7573746f726530313233343536373839 -iv 7573746f726530313233343536373839 

dpMyN7L5HI8VZEs1biQJ7g ==的

的Java:

public class CryptUtil { 
    public static final String DEFAULT_KEY = ""; 

    private static CryptUtil instance; 

    private String chiperKey; 

    private CryptUtil(String chiperKey) { 
     this.chiperKey = chiperKey; 
    } 

    public static CryptUtil getInstance() { 
     if (null == instance) { 
      instance = new CryptUtil(DEFAULT_KEY); 
     } 

     return instance; 
    } 

    public static CryptUtil getInstance(String cipherkey) { 
     instance = new CryptUtil(cipherkey); 
     return instance; 
    } 

    public String aesEncrypt(String plainText) { 
      byte[] keyBytes = Arrays.copyOf(this.chiperKey.getBytes("ASCII"), 16); 

      SecretKey key = new SecretKeySpec(keyBytes, "AES"); 
      Cipher cipher = Cipher.getInstance("AES"); 
      cipher.init(Cipher.ENCRYPT_MODE, key); 

      byte[] cleartext = plainText.getBytes("UTF-8"); 
      byte[] ciphertextBytes = cipher.doFinal(cleartext); 
      final char[] encodeHex = Hex.encodeHex(ciphertextBytes); 

      return new String(encodeHex); 

     return null; 
    } 

    public static void main(String[] args) { 

     CryptUtil cryptUtil = CryptUtil.getInstance(); 
     System.out.println(cryptUtil.aesEncrypt("lun01")); 
    } 
} 

d230b216e9d65964abd4092f5c455a21

+0

是的,我想。但它仍然不能正確轉換。我編輯的問題.... –

+1

您的十六進制值'7573746f726530313233343536373839'是字符'ustore'不是''加空值,而@Artjom說 您的Java執行AES-128 ECB模式(以及PKCS#5填充哪個OpenSSL也是)。 此外,'echo'命令(在bash中內置)爲數據添加了一個換行符,但是您的Java不會,並且'openssl enc -a'將結果編碼爲base64而不是hex。修復這些: 'echo -n lun01 | openssl aes-128-ecb -K 30313233343536373839000000000000 | od -tx1'給出'0000000 d2 30 b2 16 e9 d6 59 64 ab d4 09 2f 5c 45 5a 21'匹配您的Java結果。 –

回答

3

如果無數的在線十六進制轉換器不適用,那麼您可以簡單地將您在Java中使用的密鑰打印爲十六進制。 Here是一個流行的SO問題關於這個專業

你做到了這一點後,你會看到,它仍然無法正常工作,因爲你正在使用不同的算法。

當您使用Cipher.getInstance("AES");它很可能會默認爲「AES/ECB/PKCS5Padding」,它與「aes-256-cbc」不同,因爲ECB和CBC是兩個完全不同的modes of operation。爲了防止這種模糊性,您總是可以完全符合您的密碼,例如:Cipher.getInstance("AES/CBC/PKCS5Padding");

然後你在Java中生成密鑰只有16字節長,所以在OpenSSL的匹配密碼將是「AES-128-ECB」。

由於dave_thompson_085在comment說:

  • echo增加了一個換行符,你的Java代碼中不添加。您將需要以這種方式創建明文:echo -n "lun01"。如果您使用的是Windows,請參閱this

  • 你的Java代碼輸出結果爲十六進制,所以你需要做同樣的OpenSSL中。您需要刪除的OpenSSL命令,以防止Base64編碼的-a選項,然後就可以在Linux上使用額外的命令行工具,如od二進制輸出數據與od -tx1爲十六進制的轉換。

  • 完整的命令:

    echo -n lun01 |openssl aes-128-ecb -K 30313233343536373839000000000000 |od -tx1 
    

不要使用ECB模式!它在語義上不安全。您需要至少使用隨機IV的CBC模式(檢查它是隨機的,而不只是零字節)。

甚至更​​好的是,通過例如加入HMAC標籤與一個加密-然後-MAC的方法或簡單地使用驗證模式像GCM添加​​驗證。


如果您使用的是歐洲央行以外的其他,那麼你就不能在這兩個版本的加密同樣的事情,期待出現相同的密文。由於它是隨機的,因此您需要在一個版本中加密並在另一個版本中解密以確保兼容性。

相關問題