在Flutter中解密使用AES GCM加密的数据时出现解密失败的情况。

huangapple go评论113阅读模式
英文:

AES GCM decryption failed while decrypting data encrypted in flutter

问题

我正在尝试使用Golang中的内置crypto库解密数据,该数据是在Flutter/Dart中使用steel_crypt库进行加密的。
Golang的crypto库抛出的特定错误消息是:panic: cipher: message authentication failed

我在Android模拟器上运行Flutter应用程序 (本地主机是:10.0.2.2)

> Golang版本:go1.17.6 linux/amd64 |
Flutter版本:Flutter 2.8.1 • channel stable |
Dart版本:Dart 2.15.1

Golang代码

  1. package main
  2. import (
  3. "bufio"
  4. "crypto"
  5. "crypto/aes"
  6. "crypto/cipher"
  7. "crypto/rand"
  8. "crypto/rsa"
  9. "crypto/x509"
  10. "encoding/base64"
  11. "encoding/json"
  12. "encoding/pem"
  13. "errors"
  14. "fmt"
  15. "io"
  16. "net"
  17. )
  18. func Encode(data []byte) string {
  19. hb := base64.StdEncoding.EncodeToString([]byte(data))
  20. return hb
  21. }
  22. // Decoding the base string to array of bytes
  23. func Decode(data string) []byte {
  24. hb, _ := base64.StdEncoding.DecodeString(data)
  25. return hb
  26. }
  27. // Generating RSA private key
  28. func GenerateRsaPrivateKey(size int) (*rsa.PrivateKey, error) {
  29. privateKey, err := rsa.GenerateKey(rand.Reader, size)
  30. if err != nil {
  31. return nil, err
  32. }
  33. return privateKey, nil
  34. }
  35. // Generating RSA public key
  36. func GenerateRsaPublicKey(privateKey *rsa.PrivateKey) rsa.PublicKey {
  37. return privateKey.PublicKey
  38. }
  39. // This function can be use encrypt a plain text with rsa algorithm
  40. func RsaEncrypt(publicKey rsa.PublicKey, data string) ([]byte, error) {
  41. encryptedBytes, err := rsa.EncryptPKCS1v15(
  42. rand.Reader,
  43. &publicKey,
  44. []byte(data))
  45. return encryptedBytes, err
  46. // encryptedBytes, err := rsa.EncryptOAEP(
  47. // sha256.New(),
  48. // rand.Reader,
  49. // &publicKey,
  50. // []byte(data),
  51. // nil)
  52. // return encryptedBytes, err
  53. }
  54. // This function can be use decrypt a encrypted text with rsa algorithm
  55. func RsaDecrypt(privateKey rsa.PrivateKey, data []byte) ([]byte, error) {
  56. decryptedBytes, err := privateKey.Decrypt(
  57. nil,
  58. data,
  59. &rsa.OAEPOptions{Hash: crypto.SHA256})
  60. return decryptedBytes, err
  61. }
  62. // This fucntion is used to dump/serialize the rsa public key
  63. func DumpKey(key *rsa.PublicKey) ([]byte, error) {
  64. return x509.MarshalPKCS1PublicKey(key), nil
  65. }
  66. // This function is used to load the rsa public key
  67. func LoadKey(byteKey []byte) (*rsa.PublicKey, error) {
  68. key, err := x509.ParsePKCS1PublicKey(byteKey)
  69. return key, err
  70. }
  71. // Generate fixed size byte array
  72. func GenerateAesKey(size int) []byte {
  73. token := make([]byte, size)
  74. rand.Read(token)
  75. return token
  76. }
  77. // This fucntion can be used for encrypting a plain text using AES-GCM algorithm
  78. func AesEncryption(key []byte, data string) ([]byte, error) {
  79. c, err := aes.NewCipher(key)
  80. if err != nil {
  81. return nil, err
  82. }
  83. gcm, err := cipher.NewGCM(c)
  84. if err != nil {
  85. return nil, err
  86. }
  87. nonce := make([]byte, gcm.NonceSize())
  88. if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
  89. return nil, err
  90. }
  91. cipherText := gcm.Seal(nonce, nonce, []byte(data), nil)
  92. return cipherText, nil
  93. }
  94. // This fucntion can be used for decrypting the ciphertext encrypted using AES-GCM algorithm
  95. func AesDecryption(key []byte, cipherText []byte, nonce []byte) ([]byte, error) {
  96. c, err := aes.NewCipher(key)
  97. if err != nil {
  98. fmt.Println("1")
  99. return nil, err
  100. }
  101. gcm, err := cipher.NewGCM(c)
  102. if err != nil {
  103. fmt.Println("2")
  104. return nil, err
  105. }
  106. noncesize := gcm.NonceSize()
  107. if len(cipherText) < noncesize {
  108. fmt.Println("3")
  109. return nil, err
  110. }
  111. cipherText = cipherText[noncesize:]
  112. // nonce, cipherText := cipherText[:noncesize], cipherText[noncesize:]
  113. plainText, err := gcm.Open(nil, nonce, cipherText, nil)
  114. if err != nil {
  115. fmt.Println("4", err.Error())
  116. return nil, err
  117. }
  118. return plainText, nil
  119. }
  120. func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
  121. block, _ := pem.Decode([]byte(pubPEM))
  122. if block == nil {
  123. return nil, errors.New("failed to parse PEM block containing the key")
  124. }
  125. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  126. if err != nil {
  127. return nil, err
  128. }
  129. switch pub := pub.(type) {
  130. case *rsa.PublicKey:
  131. return pub, nil
  132. default:
  133. break // fall through
  134. }
  135. return nil, errors.New("Key type is not RSA")
  136. }
  137. type trans struct {
  138. Key string `json:"key"`
  139. }
  140. type creden struct {
  141. Data []byte `json:"data"`
  142. Nonce []byte `json:"nonce"`
  143. }
  144. func startServer() {
  145. fmt.Println("Starting Server...")
  146. l, err := net.Listen("tcp", "127.0.0.1:8080")
  147. if err != nil {
  148. panic(err)
  149. }
  150. defer l.Close()
  151. c, err := l.Accept()
  152. if err != nil {
  153. panic(err)
  154. }
  155. fmt.Println("Client Connected: ", c)
  156. data, err := bufio.NewReader(c).ReadBytes('\n')
  157. if err != nil {
  158. panic(err)
  159. }
  160. var t trans
  161. err_ := json.Unmarshal(data, &t)
  162. if err != nil {
  163. panic(err_)
  164. }
  165. // fmt.Println("Key: ", t.Key)
  166. publicKey, e := ParseRsaPublicKeyFromPemStr(t.Key)
  167. if e != nil {
  168. panic(e)
  169. }
  170. // fmt.Println("Success", publicKey)
  171. var cre creden
  172. cre.Data = GenerateAesKey(32)
  173. cre.Nonce = GenerateAesKey(12)
  174. jsonRes, err := json.Marshal(cre)
  175. if err != nil {
  176. panic(err)
  177. }
  178. cipherText, e_r := RsaEncrypt(*publicKey, string(jsonRes))
  179. if e_r != nil {
  180. panic(e_r)
  181. }
  182. fmt.Println("cipherText: ", len(cipherText), " | ", cipherText)
  183. encodedCipherText := Encode(cipherText)
  184. n, err := c.Write([]byte(encodedCipherText))
  185. if err != nil {
  186. panic(err)
  187. }
  188. fmt.Println("Written back the response. Written Bytes: ", n)
  189. data2, err2 := bufio.NewReader(c).ReadBytes('\n')
  190. if err2 != nil {
  191. panic(err2)
  192. }
  193. var t2 trans
  194. err_2 := json.Unmarshal(data2, &t2)
  195. if err_2 != nil {
  196. panic(err_2)
  197. }
  198. fmt.Println("recv data: ", t2.Key)
  199. cipherText2 := Decode(t2.Key)
  200. fmt.Println("cipherText2: ", cipherText2)
  201. plainText2, err := AesDecryption(cre.Data, cipherText2, cre.Nonce)
  202. if err != nil {
  203. panic(err)
  204. }
  205. fmt.Println("plainText: ", plainText2)
  206. }
  207. func main() {
  208. startServer()
  209. }

Flutter代码

外部库:

  1. steel_crypt flutter pub add steel_crypt

  2. crypton flutter pub add crypton

只需在Flutter项目中添加以下函数,并在返回MaterialApp()之前调用它。如果在此级别之下调用此函数,它将在每次窗口刷新时执行。

  1. void connectFunc() async {
  2. Socket socket = await Socket.connect('10.0.2.2', 8080);
  3. print(socket);
  4. print("Connected...");
  5. // listen to the received data event stream
  6. RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  7. socket.listen((List<int> event) {
  8. String base64Response = utf8.decode(event);
  9. // dynamic response = base64.decode(base64Response);
  10. // print(response.length);
  11. // print(response.runtimeType);
  12. try {
  13. String plainText = rsaKeypair.privateKey.decrypt(base64Response);
  14. print(plainText);
  15. dynamic jsonData = jsonDecode(plainText);
  16. String Key = jsonData["data"];
  17. String Nonce = jsonData["nonce"];
  18. var aes = AesCrypt(key: Key, padding: PaddingAES.pkcs7);
  19. print('AES Symmetric GCM:');
  20. var crypted = aes.gcm.encrypt(inp: 'words', iv: Nonce); //encrypt
  21. // print(crypted);
  22. // print(aes.gcm.decrypt(enc: crypted, iv: Nonce)); //decrypt
  23. // print('');
  24. print("send data: " + crypted);
  25. dynamic dictData = {
  26. "key": crypted,
  27. };
  28. socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
  29. } catch (e) {
  30. print(e);
  31. }
  32. // dynamic response = jsonDecode(jsonResponse);
  33. // String key = response["data"];
  34. // String nonce = response["nonce"];
  35. });
  36. // RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  37. dynamic dictData = {
  38. "key": rsaKeypair.publicKey.toFormattedPEM(),
  39. };
  40. socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
  41. // send hello
  42. // socket.add(utf8.encode('hello from flutter/dart'));
  43. // return socket;
  44. }
英文:

I'm trying to decrypt the data in golang using the in-inbuild crypto library, the data is encrypted in flutter/dart using steel_crypt library.
The specific message that is thrown by the golang's crypto library is: panic: cipher: message authentication failed.

I'm running flutter app on Android amulator (localhost is: 10.0.2.2)

> Golang version: go1.17.6 linux/amd64 |
Flutter version: Flutter 2.8.1 • channel stable |
Dart version: Dart 2.15.1

Golang Code

  1. package main
  2. import (
  3. "bufio"
  4. "crypto"
  5. "crypto/aes"
  6. "crypto/cipher"
  7. "crypto/rand"
  8. "crypto/rsa"
  9. "crypto/x509"
  10. "encoding/base64"
  11. "encoding/json"
  12. "encoding/pem"
  13. "errors"
  14. "fmt"
  15. "io"
  16. "net"
  17. )
  18. func Encode(data []byte) string {
  19. hb := base64.StdEncoding.EncodeToString([]byte(data))
  20. return hb
  21. }
  22. // Decoding the base string to array of bytes
  23. func Decode(data string) []byte {
  24. hb, _ := base64.StdEncoding.DecodeString(data)
  25. return hb
  26. }
  27. // Generating RSA private key
  28. func GenerateRsaPrivateKey(size int) (*rsa.PrivateKey, error) {
  29. privateKey, err := rsa.GenerateKey(rand.Reader, size)
  30. if err != nil {
  31. return nil, err
  32. }
  33. return privateKey, nil
  34. }
  35. // Generating RSA public key
  36. func GenerateRsaPublicKey(privateKey *rsa.PrivateKey) rsa.PublicKey {
  37. return privateKey.PublicKey
  38. }
  39. // This function can be use encrypt a plain text with rsa algorithm
  40. func RsaEncrypt(publicKey rsa.PublicKey, data string) ([]byte, error) {
  41. encryptedBytes, err := rsa.EncryptPKCS1v15(
  42. rand.Reader,
  43. &publicKey,
  44. []byte(data))
  45. return encryptedBytes, err
  46. // encryptedBytes, err := rsa.EncryptOAEP(
  47. // sha256.New(),
  48. // rand.Reader,
  49. // &publicKey,
  50. // []byte(data),
  51. // nil)
  52. // return encryptedBytes, err
  53. }
  54. // This function can be use decrypt a encrypted text with rsa algorithm
  55. func RsaDecrypt(privateKey rsa.PrivateKey, data []byte) ([]byte, error) {
  56. decryptedBytes, err := privateKey.Decrypt(
  57. nil,
  58. data,
  59. &rsa.OAEPOptions{Hash: crypto.SHA256})
  60. return decryptedBytes, err
  61. }
  62. // This fucntion is used to dump/serialize the rsa public key
  63. func DumpKey(key *rsa.PublicKey) ([]byte, error) {
  64. return x509.MarshalPKCS1PublicKey(key), nil
  65. }
  66. // This function is used to load the rsa public key
  67. func LoadKey(byteKey []byte) (*rsa.PublicKey, error) {
  68. key, err := x509.ParsePKCS1PublicKey(byteKey)
  69. return key, err
  70. }
  71. // Generate fixed size byte array
  72. func GenerateAesKey(size int) []byte {
  73. token := make([]byte, size)
  74. rand.Read(token)
  75. return token
  76. }
  77. // This fucntion can be used for encrypting a plain text using AES-GCM algorithm
  78. func AesEncryption(key []byte, data string) ([]byte, error) {
  79. c, err := aes.NewCipher(key)
  80. if err != nil {
  81. return nil, err
  82. }
  83. gcm, err := cipher.NewGCM(c)
  84. if err != nil {
  85. return nil, err
  86. }
  87. nonce := make([]byte, gcm.NonceSize())
  88. if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
  89. return nil, err
  90. }
  91. cipherText := gcm.Seal(nonce, nonce, []byte(data), nil)
  92. return cipherText, nil
  93. }
  94. // This fucntion can be used for decrypting the ciphertext encrypted using AES-GCM algorithm
  95. func AesDecryption(key []byte, cipherText []byte, nonce []byte) ([]byte, error) {
  96. c, err := aes.NewCipher(key)
  97. if err != nil {
  98. fmt.Println("1")
  99. return nil, err
  100. }
  101. gcm, err := cipher.NewGCM(c)
  102. if err != nil {
  103. fmt.Println("2")
  104. return nil, err
  105. }
  106. noncesize := gcm.NonceSize()
  107. if len(cipherText) < noncesize {
  108. fmt.Println("3")
  109. return nil, err
  110. }
  111. cipherText = cipherText[noncesize:]
  112. // nonce, cipherText := cipherText[:noncesize], cipherText[noncesize:]
  113. plainText, err := gcm.Open(nil, nonce, cipherText, nil)
  114. if err != nil {
  115. fmt.Println("4", err.Error())
  116. return nil, err
  117. }
  118. return plainText, nil
  119. }
  120. func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
  121. block, _ := pem.Decode([]byte(pubPEM))
  122. if block == nil {
  123. return nil, errors.New("failed to parse PEM block containing the key")
  124. }
  125. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  126. if err != nil {
  127. return nil, err
  128. }
  129. switch pub := pub.(type) {
  130. case *rsa.PublicKey:
  131. return pub, nil
  132. default:
  133. break // fall through
  134. }
  135. return nil, errors.New("Key type is not RSA")
  136. }
  137. type trans struct {
  138. Key string `json:"key"`
  139. }
  140. type creden struct {
  141. Data []byte `json:"data"`
  142. Nonce []byte `json:"nonce"`
  143. }
  144. func startServer() {
  145. fmt.Println("Starting Server...")
  146. l, err := net.Listen("tcp", "127.0.0.1:8080")
  147. if err != nil {
  148. panic(err)
  149. }
  150. defer l.Close()
  151. c, err := l.Accept()
  152. if err != nil {
  153. panic(err)
  154. }
  155. fmt.Println("Client Connected: ", c)
  156. data, err := bufio.NewReader(c).ReadBytes('\n')
  157. if err != nil {
  158. panic(err)
  159. }
  160. var t trans
  161. err_ := json.Unmarshal(data, &t)
  162. if err != nil {
  163. panic(err_)
  164. }
  165. // fmt.Println("Key: ", t.Key)
  166. publicKey, e := ParseRsaPublicKeyFromPemStr(t.Key)
  167. if e != nil {
  168. panic(e)
  169. }
  170. // fmt.Println("Success", publicKey)
  171. var cre creden
  172. cre.Data = GenerateAesKey(32)
  173. cre.Nonce = GenerateAesKey(12)
  174. jsonRes, err := json.Marshal(cre)
  175. if err != nil {
  176. panic(err)
  177. }
  178. cipherText, e_r := RsaEncrypt(*publicKey, string(jsonRes))
  179. if e_r != nil {
  180. panic(e_r)
  181. }
  182. fmt.Println("cipherText: ", len(cipherText), " | ", cipherText)
  183. encodedCipherText := Encode(cipherText)
  184. n, err := c.Write([]byte(encodedCipherText))
  185. if err != nil {
  186. panic(err)
  187. }
  188. fmt.Println("Written back the response. Written Bytes: ", n)
  189. data2, err2 := bufio.NewReader(c).ReadBytes('\n')
  190. if err2 != nil {
  191. panic(err2)
  192. }
  193. var t2 trans
  194. err_2 := json.Unmarshal(data2, &t2)
  195. if err_2 != nil {
  196. panic(err_2)
  197. }
  198. fmt.Println("recv data: ", t2.Key)
  199. cipherText2 := Decode(t2.Key)
  200. fmt.Println("cipherText2: ", cipherText2)
  201. plainText2, err := AesDecryption(cre.Data, cipherText2, cre.Nonce)
  202. if err != nil {
  203. panic(err)
  204. }
  205. fmt.Println("plainText: ", plainText2)
  206. }
  207. func main() {
  208. startServer()
  209. }

Flutter Code

External Libraries:

  1. steel_crypt flutter pub add steel_crypt.

  2. crypton flutter pub add crypton.

Just add below function in your flutter project and call it just before returning the MaterialApp(). If you call this function below this level it will get executed every time windows refres.

  1. void connectFunc() async {
  2. Socket socket = await Socket.connect('10.0.2.2', 8080);
  3. print(socket);
  4. print("Connected...");
  5. // listen to the received data event stream
  6. RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  7. socket.listen((List<int> event) {
  8. String base64Response = utf8.decode(event);
  9. // dynamic response = base64.decode(base64Response);
  10. // print(response.length);
  11. // print(response.runtimeType);
  12. try {
  13. String plainText = rsaKeypair.privateKey.decrypt(base64Response);
  14. print(plainText);
  15. dynamic jsonData = jsonDecode(plainText);
  16. String Key = jsonData["data"];
  17. String Nonce = jsonData["nonce"];
  18. var aes = AesCrypt(key: Key, padding: PaddingAES.pkcs7);
  19. print('AES Symmetric GCM:');
  20. var crypted = aes.gcm.encrypt(inp: 'words', iv: Nonce); //encrypt
  21. // print(crypted);
  22. // print(aes.gcm.decrypt(enc: crypted, iv: Nonce)); //decrypt
  23. // print('');
  24. print("send data: " + crypted);
  25. dynamic dictData = {
  26. "key": crypted,
  27. };
  28. socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
  29. } catch (e) {
  30. print(e);
  31. }
  32. // dynamic response = jsonDecode(jsonResponse);
  33. // String key = response["data"];
  34. // String nonce = response["nonce"];
  35. });
  36. // RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  37. dynamic dictData = {
  38. "key": rsaKeypair.publicKey.toFormattedPEM(),
  39. };
  40. socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
  41. // send hello
  42. // socket.add(utf8.encode('hello from flutter/dart'));
  43. // return socket;
  44. }

答案1

得分: 1

我已经找到了问题的解决方案。解决方案是在Flutter/Dart中使用另一个名为cryptography的库来加密数据。在Golang方面没有错误(除了一些修改)。

在Golang端修改了AesDecrypt函数:

  1. func AesDecryption(key []byte, cipherText []byte, nonce []byte) ([]byte, error) {
  2. c, err := aes.NewCipher(key)
  3. if err != nil {
  4. fmt.Println("1")
  5. return nil, err
  6. }
  7. gcm, err := cipher.NewGCM(c)
  8. if err != nil {
  9. fmt.Println("2")
  10. return nil, err
  11. }
  12. // noncesize := gcm.NonceSize()
  13. // if len(cipherText) < noncesize {
  14. // fmt.Println("3")
  15. // return nil, err
  16. // }
  17. // cipherText = cipherText[noncesize:]
  18. // nonce, cipherText := cipherText[:noncesize], cipherText[noncesize:]
  19. plainText, err := gcm.Open(nil, nonce, cipherText, nil)
  20. if err != nil {
  21. fmt.Println("4", err.Error())
  22. return nil, err
  23. }
  24. return plainText, nil
  25. }

现在整个修改后的startServer函数如下:

  1. func startServer(nonce []byte, key []byte) {
  2. fmt.Println("Starting Server...")
  3. l, err := net.Listen("tcp", "127.0.0.1:8080")
  4. if err != nil {
  5. panic(err)
  6. }
  7. defer l.Close()
  8. c, err := l.Accept()
  9. if err != nil {
  10. panic(err)
  11. }
  12. fmt.Println("Client Connected: ", c)
  13. data, err := bufio.NewReader(c).ReadBytes('\n')
  14. if err != nil {
  15. panic(err)
  16. }
  17. var t trans
  18. err_ := json.Unmarshal(data, &t)
  19. if err != nil {
  20. panic(err_)
  21. }
  22. // fmt.Println("Key: ", t.Key)
  23. publicKey, e := ParseRsaPublicKeyFromPemStr(t.Key)
  24. if e != nil {
  25. panic(e)
  26. }
  27. // fmt.Println("Success", publicKey)
  28. var cre creden
  29. cre.Data = Encode(key) //GenerateAesKey(32)
  30. cre.Nonce = Encode(nonce) //GenerateAesKey(12)
  31. jsonRes, err := json.Marshal(cre)
  32. if err != nil {
  33. panic(err)
  34. }
  35. cipherText, e_r := RsaEncrypt(*publicKey, string(jsonRes))
  36. if e_r != nil {
  37. panic(e_r)
  38. }
  39. // fmt.Println("cipherText: ", len(cipherText), " | ", cipherText)
  40. encodedCipherText := Encode(cipherText)
  41. n, err := c.Write([]byte(encodedCipherText))
  42. if err != nil {
  43. panic(err)
  44. }
  45. fmt.Println("Written back the response. Written Bytes: ", n)
  46. data2, err2 := bufio.NewReader(c).ReadBytes('\n')
  47. if err2 != nil {
  48. panic(err2)
  49. }
  50. var t2 trans
  51. err_2 := json.Unmarshal(data2, &t2)
  52. if err_2 != nil {
  53. panic(err_2)
  54. }
  55. fmt.Println("recv data: ", t2.Key)
  56. cipherText2 := Decode(t2.Key)
  57. fmt.Println("cipherText2: ", cipherText2)
  58. plainText2, err := AesDecryption(key, cipherText2, nonce)
  59. if err != nil {
  60. panic(err)
  61. }
  62. fmt.Println("plainText: ", string(plainText2))
  63. }

现在解决方案的Flutter部分如下:
外部依赖:cryptography: ^2.0.5

  1. void connectFunc() async {
  2. Socket socket = await Socket.connect('10.0.2.2', 8080);
  3. print(socket);
  4. print("Connected...");
  5. // listen to the received data event stream
  6. RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  7. socket.listen((List<int> event) async {
  8. String base64Response = utf8.decode(event);
  9. try {
  10. String plainText = rsaKeypair.privateKey.decrypt(base64Response);
  11. dynamic jsonData = jsonDecode(plainText);
  12. String Key = jsonData["data"];
  13. String Nonce = jsonData["nonce"];
  14. String message = "Hello World";
  15. final algorithm = AesGcm.with256bits();
  16. final secretBox = await algorithm.encrypt(
  17. message.codeUnits,
  18. secretKey: SecretKey(base64.decode(jsonData["data"])),
  19. nonce: base64.decode(jsonData["nonce"]),
  20. );
  21. print("key: ${base64.decode(jsonData["data"])}");
  22. print("nonce: ${base64.decode(jsonData["nonce"])}");
  23. print("secretBox: ${secretBox.concatenation(nonce: false)}");
  24. dynamic dictData = {
  25. "key": base64.encode(secretBox.concatenation(nonce: false)),
  26. };
  27. socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
  28. } catch (e) {
  29. print(e);
  30. }
  31. });
  32. dynamic dictData = {
  33. "key": rsaKeypair.publicKey.toFormattedPEM(),
  34. };
  35. socket.add(utf8.encode(jsonEncode(dictData) + "\n"));
  36. }
英文:

I have found the solution of the problem.
The solution is that we have to use another library called cryptography to encrypt the data in flutter/dart.
There is no error at golang side ( except some modifications ).

AesDecrypt function at the golang side have been modified

  1. func AesDecryption(key []byte, cipherText []byte, nonce []byte) ([]byte, error) {
  2. c, err := aes.NewCipher(key)
  3. if err != nil {
  4. fmt.Println(&quot;1&quot;)
  5. return nil, err
  6. }
  7. gcm, err := cipher.NewGCM(c)
  8. if err != nil {
  9. fmt.Println(&quot;2&quot;)
  10. return nil, err
  11. }
  12. // noncesize := gcm.NonceSize()
  13. // if len(cipherText) &lt; noncesize {
  14. // fmt.Println(&quot;3&quot;)
  15. // return nil, err
  16. // }
  17. // cipherText = cipherText[noncesize:]
  18. // nonce, cipherText := cipherText[:noncesize], cipherText[noncesize:]
  19. plainText, err := gcm.Open(nil, nonce, cipherText, nil)
  20. if err != nil {
  21. fmt.Println(&quot;4&quot;, err.Error())
  22. return nil, err
  23. }
  24. return plainText, nil
  25. }

Now the whole revised startServer function in here:

  1. func startServer(nonce []byte, key []byte) {
  2. fmt.Println(&quot;Starting Server...&quot;)
  3. l, err := net.Listen(&quot;tcp&quot;, &quot;127.0.0.1:8080&quot;)
  4. if err != nil {
  5. panic(err)
  6. }
  7. defer l.Close()
  8. c, err := l.Accept()
  9. if err != nil {
  10. panic(err)
  11. }
  12. fmt.Println(&quot;Client Connected: &quot;, c)
  13. data, err := bufio.NewReader(c).ReadBytes(&#39;\n&#39;)
  14. if err != nil {
  15. panic(err)
  16. }
  17. var t trans
  18. err_ := json.Unmarshal(data, &amp;t)
  19. if err != nil {
  20. panic(err_)
  21. }
  22. // fmt.Println(&quot;Key: &quot;, t.Key)
  23. publicKey, e := ParseRsaPublicKeyFromPemStr(t.Key)
  24. if e != nil {
  25. panic(e)
  26. }
  27. // fmt.Println(&quot;Success&quot;, publicKey)
  28. var cre creden
  29. cre.Data = Encode(key) //GenerateAesKey(32)
  30. cre.Nonce = Encode(nonce) //GenerateAesKey(12)
  31. jsonRes, err := json.Marshal(cre)
  32. if err != nil {
  33. panic(err)
  34. }
  35. cipherText, e_r := RsaEncrypt(*publicKey, string(jsonRes))
  36. if e_r != nil {
  37. panic(e_r)
  38. }
  39. // fmt.Println(&quot;cipherText: &quot;, len(cipherText), &quot; | &quot;, cipherText)
  40. encodedCipherText := Encode(cipherText)
  41. n, err := c.Write([]byte(encodedCipherText))
  42. if err != nil {
  43. panic(err)
  44. }
  45. fmt.Println(&quot;Written back the response. Written Bytes: &quot;, n)
  46. data2, err2 := bufio.NewReader(c).ReadBytes(&#39;\n&#39;)
  47. if err2 != nil {
  48. panic(err2)
  49. }
  50. var t2 trans
  51. err_2 := json.Unmarshal(data2, &amp;t2)
  52. if err_2 != nil {
  53. panic(err_2)
  54. }
  55. fmt.Println(&quot;recv data: &quot;, t2.Key)
  56. cipherText2 := Decode(t2.Key)
  57. fmt.Println(&quot;cipherText2: &quot;, cipherText2)
  58. plainText2, err := AesDecryption(key, cipherText2, nonce)
  59. if err != nil {
  60. panic(err)
  61. }
  62. fmt.Println(&quot;plainText: &quot;, string(plainText2))
  63. }

And now the flutter side of solution:
external denepencies: cryptography: ^2.0.5

  1. void connectFunc() async {
  2. Socket socket = await Socket.connect(&#39;10.0.2.2&#39;, 8080);
  3. print(socket);
  4. print(&quot;Connected...&quot;);
  5. // listen to the received data event stream
  6. RSAKeypair rsaKeypair = RSAKeypair.fromRandom();
  7. socket.listen((List&lt;int&gt; event) async {
  8. String base64Response = utf8.decode(event);
  9. try {
  10. String plainText = rsaKeypair.privateKey.decrypt(base64Response);
  11. dynamic jsonData = jsonDecode(plainText);
  12. String Key = jsonData[&quot;data&quot;];
  13. String Nonce = jsonData[&quot;nonce&quot;];
  14. String message = &quot;Hello World&quot;;
  15. final algorithm = AesGcm.with256bits();
  16. final secretBox = await algorithm.encrypt(
  17. message.codeUnits,
  18. secretKey: SecretKey(base64.decode(jsonData[&quot;data&quot;])),
  19. nonce: base64.decode(jsonData[&quot;nonce&quot;]),
  20. );
  21. print(&quot;key: ${base64.decode(jsonData[&quot;data&quot;])}&quot;);
  22. print(&quot;nonce: ${base64.decode(jsonData[&quot;nonce&quot;])}&quot;);
  23. print(&quot;secretBox: ${secretBox.concatenation(nonce: false)}&quot;);
  24. dynamic dictData = {
  25. &quot;key&quot;: base64.encode(secretBox.concatenation(nonce: false)),
  26. };
  27. socket.add(utf8.encode(jsonEncode(dictData) + &quot;\n&quot;));
  28. } catch (e) {
  29. print(e);
  30. }
  31. });
  32. dynamic dictData = {
  33. &quot;key&quot;: rsaKeypair.publicKey.toFormattedPEM(),
  34. };
  35. socket.add(utf8.encode(jsonEncode(dictData) + &quot;\n&quot;));
  36. }

huangapple
  • 本文由 发表于 2022年1月15日 21:16:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/70721787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定