错误 aesGCMOpen 得到密码:消息身份验证失败:golang 解密 gcm

问题描述 投票:0回答:1

我正在尝试将rails activesupport解密重写为golang,但出现此错误

err aesGCMOpen got cipher: message authentication failed

这里是主动支持解密的rails代码

class Crypton
  SECRET_KEY_BASE = ENV["SECRET_KEY_BASE"]
  class << self
    def encrypt text
        raise 'Encypt failed, secret_key_base not found' unless SECRET_KEY_BASE.present?
        text = text.to_s unless text.is_a? String
  
        len   = ActiveSupport::MessageEncryptor.key_len
        salt  = SecureRandom.hex len
        key   = ActiveSupport::KeyGenerator.new(SECRET_KEY_BASE).generate_key salt, len
        crypt = ActiveSupport::MessageEncryptor.new key
        encrypted_data = crypt.encrypt_and_sign text
        "#{salt}$$#{encrypted_data}"
    end
    def decrypt text
      raise 'Decrypt failed, secret_key_base not found' unless SECRET_KEY_BASE.present?
      salt, data = text.split "$$"

      len   = ActiveSupport::MessageEncryptor.key_len
      key   = ActiveSupport::KeyGenerator.new(SECRET_KEY_BASE).generate_key salt, len
      crypt = ActiveSupport::MessageEncryptor.new key
      crypt.decrypt_and_verify data
    end
  end
end

这是我的golang代码,我尝试从rails解密activesupport重写

// DecryptGCM
// reference on Rails 5.2-stable:
// https://github.com/rails/rails/blob/5-2-stable/activesupport/lib/active_support/message_encryptor.rb#L183
func DecryptGCM(encryptedText string, secretKeyBase string) (string, error) {
    encryptText := strings.Split(encryptedText, "$$")
    saltHex := encryptText[0]
    encodedText := encryptText[1]

    splitEncodedText := strings.Split(encodedText, "--")
    encodedText = splitEncodedText[0]
    ivText := splitEncodedText[1]
    authTagText := splitEncodedText[2]

    decodeText, err := base64.StdEncoding.DecodeString(encodedText)
    if err != nil {
        return "", fmt.Errorf(`err b64 decode text got %v`, err)
    }

    ivDecodeText, err := base64.StdEncoding.DecodeString(ivText)
    if err != nil {
        return "", fmt.Errorf(`err b64 iv got %v`, err)
    }

    authTagTextDecoded, err := base64.StdEncoding.DecodeString(authTagText)
    if err != nil {
        return "", fmt.Errorf(`err b64 auth tag got %v`, err)
    }

    key := GenerateKey(secretKeyBase, saltHex)

    block, err := aes.NewCipher(key)
    if err != nil {
        return "", fmt.Errorf(`err aesNewCipher got %v`, err)
    }

    aesGCM, err := cipher.NewGCM(block)
    if err != nil {
        return "", fmt.Errorf(`err chipperNewGCM got %v`, err)
    }

    plaintext, err := aesGCM.Open(nil, ivDecodeText, decodeText, authTagTextDecoded)
    if err != nil {
        return "", fmt.Errorf(`err aesGCMOpen got %v`, err)
    }

    return string(plaintext), nil
}

func GenerateKey(secretKeyBase string, saltHex string) []byte {
    key := pbkdf2.Key([]byte(secretKeyBase), []byte(saltHex), 65536, 32, sha1.New)
    return key
}

func TestMain(t *testing.T) {
    encryptText := "7c7eb6202943398b0d0619d008d226372f1b3b341eb39500eab71c3b67b7f641$$hDJ5e+6QkoCjk4cqT+hAY9c7Jj7Hxg==--t9hrqWnzQeeJTffr--1bHoguSmIkYQrpI1cd/KRQ=="


    decrypted, err := DecryptGCM(encryptText, SECRET_KEY)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Decrypted:", decrypted)
    }
}

关键是:

SECRET_KEY_BASE="3ae9b0ce19316f877554a0427044180e27267fb9798db9147feeb318865b3a52f79824201608f6e4e10dc8e3f29e5bf4b83e46c4103ff8d98b99903d054d720i"

我从这个rails命令生成了加密数据

Crypton.encrypt("hello, world")

如果您找到任何解决方案,请发表评论,

谢谢你

可以从rails加密中解密加密数据

ruby-on-rails go encryption activesupport
1个回答
0
投票

在Go代码的

Open()
调用中,密文和认证标签必须串联传递(在第三个参数中)。对于附加数据,必须传递
nil
(在第4个参数中)。
此外,解密的数据必须被反序列化,为此必须使用合适的库,例如红宝石元帅

import (
    "bytes"
    rbmarshal "github.com/dozen/ruby-marshal"
    ...
)

...

func DecryptGCM(encryptedText string, secretKeyBase string) (string, error) {
    
    ...
    
    plaintext, err := aesGCM.Open(nil, ivDecodeText, append(decodeText, authTagTextDecoded...), nil) // Fix 1
    if err != nil {
        return "", fmt.Errorf(`err aesGCMOpen got %v`, err)
    }

    var v string
    rbmarshal.NewDecoder(bytes.NewReader(plaintext)).Decode(&v) // Fix 2
    return string(v), nil
}

通过这些更改,使用 Rails 代码加密的数据可以使用 Go 代码成功解密。

© www.soinside.com 2019 - 2024. All rights reserved.