簡體   English   中英

AES-CTR 在 Go 中加密,在 CryptoJS 中解密

[英]AES-CTR Encrypt in Go and decrypt in CryptoJS

我在使用 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("1234567890123456")
    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 密文從 GO 復制到 JS(或反之亦然)時,它不起作用。 我還注意到 js output 的第一部分與 Go output 相同,但在 js output 中有比 Go 中更多的字節。

我的目的是加密GO中的一些文本,然后將Base64密文發送給可以解密的JS。

謝謝

好的,這是您要解決的問題:

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

  2. 加密/解密時,請指定參數: padding: CryptoJS.pad.NoPadding

CTR模式不需要在加密前填充純文本。
從多個AES塊生成的密鑰流在XORing之前被修整以匹配純文本長度。
看起來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> 

您必須在編碼之前在純文本中添加填充

例如:

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)

更新:2023

// CryotoJS CDN
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js" integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

let config = {
    mode: CryptoJS.mode.CTR,
    iv: CryptoJS.enc.Utf8.parse('YourInitialVector'),
    padding: CryptoJS.pad.NoPadding
};

let dataObjString = JSON.stringify(YourDataObj);

let ciphertext = CryptoJS.AES.encrypt(dataObjString, CryptoJS.enc.Utf8.parse('YourEncryptionKey'), config).toString();

console.log("Encrypted ", ciphertext);

let bytes = CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse('YourEncryptionKey'), config);
                
console.log("Decrypted ", JSON.parse(bytes.toString(CryptoJS.enc.Utf8)));

參考:

希望這會有所幫助。 干杯:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM