首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >加密数据时,AES GCM解密失败

加密数据时,AES GCM解密失败
EN

Stack Overflow用户
提问于 2022-01-15 13:16:05
回答 1查看 933关注 0票数 0

我试图使用内置的加密库解密戈朗中的数据,使用地窖库对数据进行加密。戈朗的密码库抛出的特定消息是:panic: cipher: message authentication failed

我正在安卓模拟器上运行颤振应用程序(本地主机是: 10.0.2.2)

Golang版本: go1.17.6 linux/amd64 64\x\x\x{e76f}颤振版本: Flutter 2.8.1·声道稳定+ Dart版本: Dart 2.15.1

Golang码

代码语言:javascript
运行
复制
package main

import (
    "bufio"
    "crypto"
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/base64"
    "encoding/json"
    "encoding/pem"
    "errors"
    "fmt"
    "io"
    "net"
)

func Encode(data []byte) string {
    hb := base64.StdEncoding.EncodeToString([]byte(data))
    return hb
}

// Decoding the base string to array of bytes
func Decode(data string) []byte {
    hb, _ := base64.StdEncoding.DecodeString(data)
    return hb
}

// Generating RSA private key
func GenerateRsaPrivateKey(size int) (*rsa.PrivateKey, error) {
    privateKey, err := rsa.GenerateKey(rand.Reader, size)
    if err != nil {
        return nil, err
    }
    return privateKey, nil
}

// Generating RSA public key
func GenerateRsaPublicKey(privateKey *rsa.PrivateKey) rsa.PublicKey {
    return privateKey.PublicKey
}

// This function can be use encrypt a plain text with rsa algorithm
func RsaEncrypt(publicKey rsa.PublicKey, data string) ([]byte, error) {

    encryptedBytes, err := rsa.EncryptPKCS1v15(
        rand.Reader,
        &publicKey,
        []byte(data))
    return encryptedBytes, err

    // encryptedBytes, err := rsa.EncryptOAEP(
    //  sha256.New(),
    //  rand.Reader,
    //  &publicKey,
    //  []byte(data),
    //  nil)
    // return encryptedBytes, err
}

// This function can be use decrypt a encrypted text with rsa algorithm
func RsaDecrypt(privateKey rsa.PrivateKey, data []byte) ([]byte, error) {
    decryptedBytes, err := privateKey.Decrypt(
        nil,
        data,
        &rsa.OAEPOptions{Hash: crypto.SHA256})
    return decryptedBytes, err
}

//  This fucntion is used to dump/serialize the rsa public key
func DumpKey(key *rsa.PublicKey) ([]byte, error) {
    return x509.MarshalPKCS1PublicKey(key), nil
}

// This function is used to load the rsa public key
func LoadKey(byteKey []byte) (*rsa.PublicKey, error) {
    key, err := x509.ParsePKCS1PublicKey(byteKey)
    return key, err
}

// Generate fixed size byte array
func GenerateAesKey(size int) []byte {
    token := make([]byte, size)
    rand.Read(token)
    return token
}

// This fucntion can be used for encrypting a plain text using AES-GCM algorithm
func AesEncryption(key []byte, data string) ([]byte, error) {
    c, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }

    gcm, err := cipher.NewGCM(c)
    if err != nil {
        return nil, err
    }

    nonce := make([]byte, gcm.NonceSize())
    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
        return nil, err
    }

    cipherText := gcm.Seal(nonce, nonce, []byte(data), nil)
    return cipherText, nil
}

// This fucntion can be used for decrypting the ciphertext encrypted using AES-GCM algorithm
func AesDecryption(key []byte, cipherText []byte, nonce []byte) ([]byte, error) {
    c, err := aes.NewCipher(key)
    if err != nil {
        fmt.Println("1")
        return nil, err
    }
    gcm, err := cipher.NewGCM(c)

    if err != nil {
        fmt.Println("2")
        return nil, err
    }

    noncesize := gcm.NonceSize()
    if len(cipherText) < noncesize {
        fmt.Println("3")
        return nil, err
    }

    cipherText = cipherText[noncesize:]

    // nonce, cipherText := cipherText[:noncesize], cipherText[noncesize:]

    plainText, err := gcm.Open(nil, nonce, cipherText, nil)

    if err != nil {
        fmt.Println("4", err.Error())
        return nil, err
    }

    return plainText, nil
}

func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
    block, _ := pem.Decode([]byte(pubPEM))
    if block == nil {
        return nil, errors.New("failed to parse PEM block containing the key")
    }

    pub, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        return nil, err
    }

    switch pub := pub.(type) {
    case *rsa.PublicKey:
        return pub, nil
    default:
        break // fall through
    }
    return nil, errors.New("Key type is not RSA")
}

type trans struct {
    Key string `json:"key"`
}


type creden struct {
    Data  []byte `json:"data"`
    Nonce []byte `json:"nonce"`
}

func startServer() {
    fmt.Println("Starting Server...")
    l, err := net.Listen("tcp", "127.0.0.1:8080")

    if err != nil {
        panic(err)
    }

    defer l.Close()

    c, err := l.Accept()

    if err != nil {
        panic(err)
    }

    fmt.Println("Client Connected: ", c)

    data, err := bufio.NewReader(c).ReadBytes('\n')

    if err != nil {
        panic(err)
    }

    var t trans

    err_ := json.Unmarshal(data, &t)

    if err != nil {
        panic(err_)
    }

    // fmt.Println("Key: ", t.Key)

    publicKey, e := ParseRsaPublicKeyFromPemStr(t.Key)

    if e != nil {
        panic(e)
    }

    // fmt.Println("Success", publicKey)

    var cre creden
    cre.Data = GenerateAesKey(32)
    cre.Nonce = GenerateAesKey(12)

    jsonRes, err := json.Marshal(cre)

    if err != nil {
        panic(err)
    }

    cipherText, e_r := RsaEncrypt(*publicKey, string(jsonRes))

    if e_r != nil {
        panic(e_r)
    }

    fmt.Println("cipherText: ", len(cipherText), " | ", cipherText)

    encodedCipherText := Encode(cipherText)

    n, err := c.Write([]byte(encodedCipherText))

    if err != nil {
        panic(err)
    }

    fmt.Println("Written back the response. Written Bytes: ", n)

    data2, err2 := bufio.NewReader(c).ReadBytes('\n')

    if err2 != nil {
        panic(err2)
    }

    var t2 trans

    err_2 := json.Unmarshal(data2, &t2)

    if err_2 != nil {
        panic(err_2)
    }

    fmt.Println("recv data: ", t2.Key)

    cipherText2 := Decode(t2.Key)

    fmt.Println("cipherText2: ", cipherText2)

    plainText2, err := AesDecryption(cre.Data, cipherText2, cre.Nonce)

    if err != nil {
        panic(err)
    }

    fmt.Println("plainText: ", plainText2)

}

func main() {
    startServer()
}

颤振程序

外部图书馆:

  1. steel_crypt flutter pub add steel_crypt.
  2. crypton flutter pub add crypton.

只需在您的颤振项目中添加下面的函数,并在返回MaterialApp()之前调用它。如果您在此级别以下调用此函数,则每次windows刷新时都会执行该函数。

代码语言:javascript
运行
复制
void connectFunc() async {
  Socket socket = await Socket.connect('10.0.2.2', 8080);
  print(socket);
  print("Connected...");

  // listen to the received data event stream

  RSAKeypair rsaKeypair = RSAKeypair.fromRandom();

  socket.listen((List<int> event) {
    String base64Response = utf8.decode(event);
    // dynamic response = base64.decode(base64Response);

    // print(response.length);
    // print(response.runtimeType);

    try {
      String plainText = rsaKeypair.privateKey.decrypt(base64Response);
      print(plainText);

      dynamic jsonData = jsonDecode(plainText);

      String Key = jsonData["data"];
      String Nonce = jsonData["nonce"];

      var aes = AesCrypt(key: Key, padding: PaddingAES.pkcs7);

      print('AES Symmetric GCM:');
      var crypted = aes.gcm.encrypt(inp: 'words', iv: Nonce); //encrypt
      // print(crypted);
      // print(aes.gcm.decrypt(enc: crypted, iv: Nonce)); //decrypt
      // print('');

      print("send data: " + crypted);

      dynamic dictData = {
        "key": crypted,
      };

      socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
    } catch (e) {
      print(e);
    }

    // dynamic response = jsonDecode(jsonResponse);
    // String key = response["data"];
    // String nonce = response["nonce"];
  });
  // RSAKeypair rsaKeypair = RSAKeypair.fromRandom();

  dynamic dictData = {
    "key": rsaKeypair.publicKey.toFormattedPEM(),
  };

  socket.add(utf8.encode(jsonEncode(dictData) + "\n"));

  // send hello
  // socket.add(utf8.encode('hello from flutter/dart'));

  // return socket;
}
EN

回答 1

Stack Overflow用户

发布于 2022-01-15 19:31:19

我已经找到了这个问题的解决办法。解决方案是,我们必须使用另一个名为密码学的库来加密数据。在金刚一侧没有错误(除了一些修改)。

金边的AesDecrypt函数已被修改

代码语言:javascript
运行
复制
func AesDecryption(key []byte, cipherText []byte, nonce []byte) ([]byte, error) {
    c, err := aes.NewCipher(key)
    if err != nil {
        fmt.Println("1")
        return nil, err
    }
    gcm, err := cipher.NewGCM(c)

    if err != nil {
        fmt.Println("2")
        return nil, err
    }

    // noncesize := gcm.NonceSize()
    // if len(cipherText) < noncesize {
    //  fmt.Println("3")
    //  return nil, err
    // }

    // cipherText = cipherText[noncesize:]

    // nonce, cipherText := cipherText[:noncesize], cipherText[noncesize:]

    plainText, err := gcm.Open(nil, nonce, cipherText, nil)

    if err != nil {
        fmt.Println("4", err.Error())
        return nil, err
    }

    return plainText, nil
}

现在,在这里修改了整个startServer函数:

代码语言:javascript
运行
复制
func startServer(nonce []byte, key []byte) {
    fmt.Println("Starting Server...")
    l, err := net.Listen("tcp", "127.0.0.1:8080")

    if err != nil {
        panic(err)
    }

    defer l.Close()

    c, err := l.Accept()

    if err != nil {
        panic(err)
    }

    fmt.Println("Client Connected: ", c)

    data, err := bufio.NewReader(c).ReadBytes('\n')

    if err != nil {
        panic(err)
    }

    var t trans

    err_ := json.Unmarshal(data, &t)

    if err != nil {
        panic(err_)
    }

    // fmt.Println("Key: ", t.Key)

    publicKey, e := ParseRsaPublicKeyFromPemStr(t.Key)

    if e != nil {
        panic(e)
    }

    // fmt.Println("Success", publicKey)

    var cre creden
    cre.Data = Encode(key)    //GenerateAesKey(32)
    cre.Nonce = Encode(nonce) //GenerateAesKey(12)

    jsonRes, err := json.Marshal(cre)

    if err != nil {
        panic(err)
    }

    cipherText, e_r := RsaEncrypt(*publicKey, string(jsonRes))

    if e_r != nil {
        panic(e_r)
    }

    // fmt.Println("cipherText: ", len(cipherText), " | ", cipherText)

    encodedCipherText := Encode(cipherText)

    n, err := c.Write([]byte(encodedCipherText))

    if err != nil {
        panic(err)
    }

    fmt.Println("Written back the response. Written Bytes: ", n)

    data2, err2 := bufio.NewReader(c).ReadBytes('\n')

    if err2 != nil {
        panic(err2)
    }

    var t2 trans

    err_2 := json.Unmarshal(data2, &t2)

    if err_2 != nil {
        panic(err_2)
    }

    fmt.Println("recv data: ", t2.Key)

    cipherText2 := Decode(t2.Key)

    fmt.Println("cipherText2: ", cipherText2)

    plainText2, err := AesDecryption(key, cipherText2, nonce)

    if err != nil {
        panic(err)
    }

    fmt.Println("plainText: ", string(plainText2))

}

现在解决方案的颤振面:外部密度:cryptography: ^2.0.5

代码语言:javascript
运行
复制
void connectFunc() async {
  Socket socket = await Socket.connect('10.0.2.2', 8080);
  print(socket);
  print("Connected...");

  // listen to the received data event stream

  RSAKeypair rsaKeypair = RSAKeypair.fromRandom();

  socket.listen((List<int> event) async {
    String base64Response = utf8.decode(event);

    try {
      String plainText = rsaKeypair.privateKey.decrypt(base64Response);

      dynamic jsonData = jsonDecode(plainText);

      String Key = jsonData["data"];
      String Nonce = jsonData["nonce"];

      String message = "Hello World";

      final algorithm = AesGcm.with256bits();

      final secretBox = await algorithm.encrypt(
        message.codeUnits,
        secretKey: SecretKey(base64.decode(jsonData["data"])),
        nonce: base64.decode(jsonData["nonce"]),
      );

      print("key: ${base64.decode(jsonData["data"])}");
      print("nonce: ${base64.decode(jsonData["nonce"])}");
      print("secretBox: ${secretBox.concatenation(nonce: false)}");

      dynamic dictData = {
        "key": base64.encode(secretBox.concatenation(nonce: false)),
      };

      socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
    } catch (e) {
      print(e);
    }
  });

  dynamic dictData = {
    "key": rsaKeypair.publicKey.toFormattedPEM(),
  };

  socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70721787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档