簡體   English   中英

在golang中編碼字符串aes-128 ecb並在js中解密

[英]encode string aes-128 ecb in golang and decrypt in js

我正在嘗試在 golang 服務器上加密字符串,我有一個 aes-128 加密工具

func EncryptAES(key []byte, plaintext string) (string, error) {
    // create cipher
    c, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }

    // allocate space for ciphered data
    out := make([]byte, len(plaintext))

    for i := 1; i <= len(plaintext)/16; i++ {
        tempBuf := make([]byte, 16)

        offset := (i - 1) * 16
        limit := offset + 16
        // encrypt
        c.Encrypt(tempBuf, []byte(plaintext[offset:limit]))

        for j := 0; j < len(tempBuf); j++ {
            out[offset+j] = tempBuf[j]
        }
    }
    // return hex string
    return hex.EncodeToString(out), nil
}

之后我試圖做類似的事情

    hasher := sha256.New()
    hasher.Write([]byte(word))
    sha := hasher.Sum(nil)

    cypherText := word + userSessionKey

    for len([]byte(cypherText))%16 != 0 {
        cypherText += "0"
    }

    sha128 := sha[:len(sha)/2]

    captchaKey, err := utils.EncryptAES([]byte(hex.EncodeToString(sha128)), cypherText)
    if err != nil {
        SendErrorResponse(ctx, fasthttp.StatusInternalServerError, []byte("error generating aes session key "+err.Error()))
        return
    }

但是對於這個密鑰和密文,我在加密/解密 aes 站點上收到此錯誤在此處輸入圖像描述

用於解碼的js func也不起作用

async function decryptAES128(key, cipherText){
    let hash = CryptoJS.SHA256(key).toString();
    hash = hash.substring(0, hash.length/2);

    console.log(hash);
    console.log(cipherText)

    const bytes = await CryptoJS.AES.decrypt(CryptoJS.enc.Hex.parse(cipherText), CryptoJS.enc.Hex.parse(hash), { mode: CryptoJS.mode.ECB });

    return CryptoJS.enc.Utf8.stringify(bytes.words)
}

什么都不打印

如果明文的大小( cypherText ,順便說一句具有誤導性)不是塊大小的整數倍(AES 為 16 字節),則 Go 代碼填充 0x30 值。 作為密鑰,使用密碼 ( word ) 的 SHA256 值的前 16 個字節的十六進制編碼的 UTF-8 編碼。 密文是十六進制編碼的。

使用 在線工具解密失敗,因為在線工具使用 PKCS#7 填充並且密文是 Base64 解碼的。 為了使解密成為可能,必須禁用默認的 PKCS#7 填充,並且必須對密文進行十六進制解碼,參見例如Cyber​​Chef

使用 JavaScript 代碼解密失敗,因為 CryptoJS 默認使用 PKCS#7 填充,密鑰是十六進制解碼的,並且密文沒有作為CipherParams對象傳遞。 為了使解密成為可能,必須禁用默認的 PKCS#7 填充,密鑰必須是 UTF-8 編碼,並且密文必須作為CipherParams對象傳遞:

 var password = 'день'; var key = CryptoJS.SHA256(password).toString(); key = key.substring(0, key.length/2); var ciphertext = '46ef70c1193fa29024595964a0eb0157c4e6602da6c1429f8a2b81146f79e798' var decrypted = CryptoJS.AES.decrypt( {ciphertext: CryptoJS.enc.Hex.parse(ciphertext)}, // Fix 1: pass a CipherParams object CryptoJS.enc.Utf8.parse(key), // Fix2: UTF-8 encode the key { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding }); // Fix 3: disable padding console.log(decrypted.toString(CryptoJS.enc.Utf8));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

給出解密的 UTF-8 解碼數據: деньBvFGlrXeWCnPTwFC00000000


安全性:歐洲央行不使用 IV,因此不安全。 如今,應用了經過身份驗證的加密(例如 GCM),但至少是一種帶有 IV 的模式(例如 CBC)。
此外,使用摘要作為密鑰派生函數(KDF)是不安全的。 為此有專門的功能(例如 Argon2 或 PBKDF2)。 另外,應該直接使用 KDF 的字節串,而不是 hex 編碼的 UTF-8 編碼,這樣會降低安全性。
應用的 0x30 填充通常是不可靠的。 更可靠的是例如 PKCS#7 填充。

暫無
暫無

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

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