dongliao4353 2019-03-22 21:30
浏览 381
已采纳

AES CBC:JavaScript / CryptoJS加密-> Golang解密

Note: This is only for personal use and learning, I am not trying to roll my own encryption for public use.

I need to AES256 encrypt a string, however my current attempts end up with a string like Salted__Vέ��|��l��ʼ8XCQlY server side when it is hex decoded. It should rather be a valid utf8 base64 string when hex-decoded, which can then be decoded to the original string. This is similar to the solution offered here, however the salt was not the actual problem (despite the answer being accepted) and I have not been able to suppress the salt op by hex decoding the iv before use (as it suggested). Is there a way to do this?

I've tried several different methods and always end up in a similar spot. My latest attempt is such:

encrypt.js

// CryptoJS.pad.NoPadding={pad:function(){},unpad:function(){}};

const SECRET = '394812730425442A472D2F423F452848';
const iv = crypto.getRandomValues(new Uint8Array(16));    

function enc(plainText) {
  var b64 = CryptoJS.AES.encrypt(plainText, SECRET, { 
    iv,
    mode: CryptoJS.mode.CBC,
    // padding: CryptoJS.pad.NoPadding
  }).toString();

  // Don't need?
  //var e64 = CryptoJS.enc.Base64.parse(b64);
  //var eHex = e64.toString(CryptoJS.enc.Hex);
  console.log("b64::", b64);

  return b64;
}

enc("SUPA_SECRET");
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

Now we take the b64 result and paste it into the JS_GEN variable in the server side golang decrypt:

decrypt.go

(golang decrypt playground)

package main

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

func main() {
    JS_GEN := "U2FsdGVkX1+CA3LZTXePlgoGqL8VkdgiDgUenZhH4kc="
    SECRET := "394812730425442A472D2F423F452848"
    //msg := "SUPER_SECRET"

    res, err := DecryptCBC(SECRET, JS_GEN)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("res::", res)
}

func DecryptCBC(secret string, target string) (string, error) {
    nilString := ""
    key, _ := hex.DecodeString(secret)
    //ciphertext, err := base64.URLEncoding.DecodeString(target)

    // Decode base64 string
    ciphertext, err := base64.StdEncoding.DecodeString(target)
    if err != nil {
        return nilString, err
    }

    // Create new cipher block
    block, err := aes.NewCipher(key)
    if err != nil {
        return nilString, err
    }

    // The IV needs to be unique, but not secure. Therefore it's common to
    // include it at the beginning of the ciphertext.
    if len(ciphertext) < aes.BlockSize {
        panic("ciphertext too short")
    }
    iv := ciphertext[:aes.BlockSize]
    ciphertext = ciphertext[aes.BlockSize:]

    // CBC mode always works in whole blocks.
    if len(ciphertext)%aes.BlockSize != 0 {
        panic("ciphertext is not a multiple of the block size")
    }
    mode := cipher.NewCBCDecrypter(block, iv)

    // CryptBlocks can work in-place if the two arguments are the same.
    mode.CryptBlocks(ciphertext, ciphertext)
    fmt.Println("ciphertext::", ciphertext)

    // Output: exampleplaintext
    return string(ciphertext), nil
}

The output will be something like:

ciphertext:: [136 227 244 124 124 92 162 254 1 147 235 213 8 136 129 150]
res:: ���||\�������

What am I doing wrong?

EDIT: I've removed hex encode/decode from the process.

</div>
  • 写回答

2条回答 默认 最新

  • dongzhi6927 2019-03-23 17:54
    关注

    I'm still not totally sure why previous attempts have failed. It could have been one of many the different ways the encryption was implemented and/or configured on both server and client.

    I've finally found what I was looking for. A simple implementation that just works out of the box. Here we will just use crypto-js and go-openssl.

    client.js

    const msg = "SUPA_SECRET"
    const key = "394812730425442A472D2F423F452848";
    const encrypted = CryptoJS.AES.encrypt(msg, key);
    
    console.log(encrypted.toString());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

    server.go

    package main
    
    import (
        "fmt"
        "github.com/Luzifer/go-openssl"
    )
    
    func main() {
        encrypted := "ENCRYPTED_STRING_HERE"
        secret := "394812730425442A472D2F423F452848"
    
        o := openssl.New()
    
        dec, err := o.DecryptBytes(secret, []byte(encrypted), openssl.DigestMD5Sum)
        if err != nil {
            fmt.Printf("An error occurred: %s
    ", err)
        }
    
        fmt.Printf("Decrypted text: %s
    ", string(dec))
    }
    
    
    
    // OUTPUT:
    // Decrypted text: SUPA_SECRET
    
    </div>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 ubuntu20.04怎么安装yolov5(已经安装anaconda)
  • ¥15 TinyMCE如何去掉自动弹出的“链接…”工具?
  • ¥15 微信支付转账凭证,如何解决
  • ¥15 在win10下使用指纹登录时,界面上的文字最后一个字产生换行现象
  • ¥20 使用AT89C51微控制器和MAX7219驱动器来实现0到99秒的秒表计数,有开始和暂停以及复位功能,下面有仿真图,请根据仿真图来设计c语言程序
  • ¥15 51单片机 双路ad同步采样
  • ¥15 使用xdocreport 生成word
  • ¥15 请教怎么用MATLAB求坐标
  • ¥15 gradle整合es,在创建索引时报错
  • ¥15 关于模型训练的一个问题