2016-04-28 249 views
0

我在使用CryptoJS解密在Go lang中加密的文本時遇到問題。AES-CTR在CryptoJS中加密並在Go中解密lang

這裏是Go代碼: https://play.golang.org/p/xCbl48T_iN

package main 

import (
    "crypto/aes" 
    "crypto/cipher" 
    "encoding/base64" 
    "fmt" 
) 

func main() { 
    key := []byte("123456789") 
    plaintext := []byte("text can be a random lenght") 

    block, err := aes.NewCipher(key) 
    if err != nil { 
     panic(err) 
    } 

    // The IV needs to be unique, but not secure. Therefore it's common to 
    // include it at the beginning of the ciphertext. 
    // BTW (only for test purpose) I don't include it 

    ciphertext := make([]byte, len(plaintext)) 

    iv := []byte{'\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f','\x0f'} 

    stream := cipher.NewCTR(block, iv) 
    stream.XORKeyStream(ciphertext, plaintext) 

    // CTR mode is the same for both encryption and decryption, so we can 
    // also decrypt that ciphertext with NewCTR. 
     base := base64.StdEncoding.EncodeToString(ciphertext) 
    fmt.Printf("encodedHEX: %x\n", ciphertext) 
    fmt.Printf("encodedBASE: %s\n", base) 

    plaintext2 := make([]byte, len(plaintext)) 
    stream = cipher.NewCTR(block, iv) 
    stream.XORKeyStream(plaintext2, ciphertext) 

    fmt.Printf("decoded: %s\n", plaintext2) 
} 

這裏是JS代碼: http://jsfiddle.net/Ltkxm64n/

var key = CryptoJS.enc.Hex.parse('31323334353637383930313233343536'); 
var iv = CryptoJS.enc.Hex.parse('0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f'); 
var encrypted = CryptoJS.AES.encrypt("text can be a random lenght", key, { 
    mode: CryptoJS.mode.CTR, 
    iv: iv 
}); 

console.log(encrypted.ciphertext.toString()); 
console.log(encrypted.toString()); 

var decrypted = CryptoJS.AES.decrypt(encrypted, key, { 
    mode: CryptoJS.mode.CTR, 
    iv: iv 
}); 
console.log(decrypted.toString(CryptoJS.enc.Utf8)); 
// text can be a random lenght 

兩個行之有效加密和解密,但是當我複製的base64密文從去JS (或反之),它不起作用。 我也注意到js輸出的第一部分與Go輸出是一樣的,但是在js輸出中比在Go中有更多的字節。

我的目的是加密GO中的一些文本,然後將Base64密文傳送給可解密它的JS。

謝謝

+0

像@ArtjomB。建議,我爲未來的讀者添加了Go代碼,感謝您提供有趣的建議! – Marco

回答

3

好吧,這裏是你做了什麼來解決這個問題:

  1. 添加無填充js到您的資源列表中:http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js

  2. 當加密/解密指定參數:加密前padding: CryptoJS.pad.NoPadding

CTR模式不需要填充純文本。
在XORing之前,從多個AES塊中生成的密鑰流被剪裁以匹配純文本長度。
看起來像CryptoJS生成的密鑰流爲xor它使用純文本但未修剪它,因爲由CryptoJS生成的密文長度不是padding: CryptoJS.pad.NoPadding始終爲16字節(與AES塊大小完全相同)的倍數。

var key = CryptoJS.enc.Hex.parse('31323334353637383930313233343536'); 
 
var iv = CryptoJS.enc.Hex.parse('0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f'); 
 
var encrypted = CryptoJS.AES.encrypt("text can be a random lenght", key, { 
 
    mode: CryptoJS.mode.CTR, 
 
    iv: iv, 
 
    padding: CryptoJS.pad.NoPadding 
 
}); 
 

 
document.getElementById("id").innerHTML = encrypted.ciphertext.toString(); 
 
document.getElementById("id2").innerHTML = encrypted.toString(); 
 

 
var decrypted = CryptoJS.AES.decrypt(encrypted, key, { 
 
    mode: CryptoJS.mode.CTR, 
 
    iv: iv, 
 
    padding: CryptoJS.pad.NoPadding 
 
}); 
 
document.getElementById("decrypt").innerHTML = decrypted.toString(CryptoJS.enc.Utf8); // text can be a random lenght
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script> 
 
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/mode-ctr.js"></script> 
 
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script> 
 
<p> Ciphertext in HEX: </p> 
 
<p id="id"> </p> 
 
<p> Ciphertext in BASE64: </p> 
 
<p id="id2"> </p> 
 
<p> PlainText: </p> 
 
<p id="decrypt"></p>

+0

非常感謝! – Marco

+0

更新了正確的庫引用在這裏的原始小提琴 - http://jsfiddle.net/xdyzekwn/ – gorillapower

0

你必須添加填充編碼之前明文它

例如:

func addPadding(data []byte, blocksize int) []byte { 

    padSize := len(data) % blocksize 
    if padSize == 0 { 
     return data 
    } 
    padSize = blocksize - padSize 
    return append(data, bytes.Repeat([]byte{byte(padSize)}, padSize)...) 
} 
//in main 
    plaintext := []byte("text can be a random lenght") 
    plaintext = addPadding(plaintext, aes.BlockSize) 
+0

感謝您的回覆,我更喜歡不添加填充密碼文本,以便儘可能節省更多的字節。但你也是對的!非常感謝! – Marco

+0

CTR模式不需要填充。 –

+0

是的@ArtjomB。,我的確誤導了這個解決方案。 CTR不需要明文中的填充以便加密,但是如果您沒有在JavaScript中指定'padding:CryptoJS.pad.NoPadding',CryptoJS會將填充添加到密文(爲了使其成爲32個字節的倍數,我認爲) – Marco