2017-05-20 5 views
1

次のコードを使用して、Javaでデータを暗号化して解読しました。暗号化と復号化は正常に動作しています。最初の16文字がありません - Java AES CBC暗号化とgolang解読

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 
import java.security.SecureRandom; 

public class MainNew { 

    public static void main(String[] args) throws Exception{ 
     String iv = getEncryptionIV(); 
     System.out.println(" iv = "+iv); 

     String encryptedData= encryptWithIVandKey(iv,encryptionKey,"hello world! golang is awesome!"); 
     System.out.println(encryptedData); 
     String decryptedData = decrypt (iv,encryptionKey,encryptedData); 
     System.out.println(decryptedData); 
    } 


    static final String encryptionKey = "[email protected]"; 


    static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) { 

     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      cipher.init(encryptMode, key, new IvParameterSpec(DatatypeConverter.parseBase64Binary(iv))); 
      byte[] data = cipher.doFinal(bytes); 

      return data; 

     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 
     return null; 

    } 



    static SecretKey generateKey(String passphrase) { 

     SecretKey key = null; 

     try { 

      key = new SecretKeySpec(passphrase.getBytes("UTF-8"), "AES"); 


     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 

     return key; 
    } 




    static String getEncryptionIV() { 
     SecureRandom random = new SecureRandom(); 
     byte[] ivBytes = new byte[16]; 
     random.nextBytes(ivBytes); 
     return DatatypeConverter.printBase64Binary(ivBytes); 
    } 

    static String encryptWithIVandKey(String iv, String passphrase, final String strToEncrypt) { 
     String encryptedStr = ""; 

     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      SecretKey key = generateKey(passphrase); 
      cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(DatatypeConverter.parseBase64Binary(iv))); 

      encryptedStr = DatatypeConverter.printBase64Binary(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); 

     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 


     return encryptedStr; 
    } 

    static String decrypt(String iv, String passphrase, String ciphertext) { 
     try { 
      SecretKey key = generateKey(passphrase); 
      byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, DatatypeConverter.parseBase64Binary(ciphertext)); 
      return new String(decrypted, "UTF-8"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println(e); 
     } 
     return ""; 
    } 

} 

しかし、私はhttps://play.golang.org/p/u4fip_ZW6aコードを使用してgolangで復号化した場合。解読された値の最初の16文字が欠落しています。あなたは遊び場で共有ゴーコードから

答えて

2

// The IV needs to be unique, but not secure. Therefore it's common to 
// include it at the beginning of the ciphertext. 
... 
iv := ciphertext[:aes.BlockSize] 
ciphertext = ciphertext[aes.BlockSize:] 

あなたが見ることができるように、このコードはIVであることをciphertextの最初の16のバイトを期待しています。

はしかし、Javaコードで、あなただけの操作を行います。

encryptedStr = DatatypeConverter.printBase64Binary(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); 

は、だから、文字列を暗号化し、それはあなたが戻って(その後、囲碁プログラムで使用して)されているすべてです。

私が見たように、Goコードは暗号文から16バイトを削除しているため、データが失われています。

私はあなたのGoコードが期待するものと一致するように文字列の先頭にIVを含むようにJavaコードを変更することをお勧めします。

あなたが読むためにJavaであなたのencryptWithIVandKey方法を変更することができます。

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKey key = generateKey(passphrase); 
     byte[] ivBytes = DatatypeConverter.parseBase64Binary(iv); 
     cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes)); 
     byte[] encBytes = cipher.doFinal(strToEncrypt.getBytes("UTF-8")); 
     // concat iv + encripted bytes 
     byte[] concat = new byte[ivBytes.length + encBytes.length]; 
     System.arraycopy(ivBytes, 0, concat, 0, ivBytes.length); 
     System.arraycopy(encBytes, 0, concat, ivBytes.length, encBytes.length); 
     encryptedStr = DatatypeConverter.printBase64Binary(concat); 

ここでの変更は、我々はIV +のBase64にエンコードする前に暗号化された文字列を連結していることです。

結果のBase64では次のようになります。

adAz5d5J3PAOuxntOe/9uMJgFHwIcdKobhRSKXwspmnxFlSlF40dtBYf9VSY34fU 

そして、あなたはあなたの移動のコードでその文字列をしようとした場合、それはあなたが期待する出力を生成します。

+0

ありがとうございました!ゴランコードhttps://play.golang.org/p/FRqIf-_gFtを変更しました。暗号文からIVを抽出しない。 –

+0

それはもう一つの選択肢でした:) – eugenioy

関連する問題