当前位置:   article > 正文

跨平台AES 256 GCM加密/解密_string encryptedwithjava = "a/boaixwjkflkvihp2cfdl

string encryptedwithjava = "a/boaixwjkflkvihp2cfdl6l/xn1qw2mshckfkrofm2xovma

目录

介绍

背景

使用代码

对于C#

C#测试控制台应用程序

C#加密/解密类

对于Java

Java测试控制台应用程序

Java加密/解密类

对于C++(Windows)

C++测试控制台应用程序

Linux库(GNU C++ 14标准)

构建步骤

crypto++

GcmAes.h

测试程序

Windows x64 C++ DLL

使用libGcmAes.so的Node和C#(.Net Core)包装器


本文的目的是为需要在多个平台上进行最强加密的项目提供一个起点。此处以及C++WindowsLinux)、JavaC#GitHub存储库中提供了示例代码。最近,一个基于Linux的动态库和一个解释如何使用它的测试程序被上传到GitHubLinux x64上的C++意味着它也可以用于NodeJS,只需创建一个包装器。同样,它也可以很容易地在苹果机器上使用。

介绍

在安全、身份管理和数据保护领域工作了一段时间后,我在公共领域发现了极少数基于AES 256 GCM算法的跨平台加密工作示例。这与Google在访问Gmail等时使用的算法相同。

本文可以帮助您实现非常强大的跨平台加密/解密。示例代码使用C++C#Java。但是,通过JNIJava本机接口)的Java和通过COMC#可以调用本机C++代码,在我的测试中,与纯JavaC#实现相比,这似乎要快得多。不过,有时人们希望在不调用本机C++层的情况下执行此操作。

对于C#,为了实现AES 256 GCM加密,我使用了Bouncy Castle加密库。本文提供的代码片段非常适合跨各种平台的加密和解密。我测试了它在Linux(使用Mono框架)和Windows上运行。

对于C++层,我使用了Crypto++。该库是跨平台兼容的(WindowsLinux 和其他库,如Solaris等)。Crypto++是一个健壮且实现良好的开源加密库。

本文不适合初学者,也不打算教授AES GCM算法。

本文为您提供了一个示例代码,以便通过您自己的修改来实现。

C++有点复杂。下载Crypto++源代码。创建一个控制台项目,并将现有Crypto++项目添加到解决方案中。然后,将控制台项目设置为启动项目,并设置生成依赖项顺序。

从文章中复制粘贴代码并更正头文件路径(如 pch.h)您也可以在项目属性中添加源代码目录以修复路径。同样,您可以更正Crypto++编译库的路径或将其添加到您的项目属性中。

本文的另一个目的是将所有三种主要的编程语言示例代码组合在一个地方。您不必搜索数千个单独的样本,其中一些样本无法按预期工作。此处的代码示例可以正常工作。

最近,一个基于Linux的动态库和一个解释如何使用它的测试程序被上传到GitHubLinux x64上的C++意味着它也可以用于NodeJS,只需创建一个包装器。同样,它也可以很容易地在苹果机器上使用。

背景

跨平台AES 256 GCM加密和解密(C++C#Java

您还可以在此处此处阅读有关Crypto++ AES GCM实现或算法本身的更多信息。

同样,可以在此处找到有关BouncyCastle的详细信息。

C#代码中使用的BouncyCastle .NET在这里。

GitHub的

使用代码

对于C#

请添加参考:

BouncyCastle.Crypto (BouncyCastle.Crypto.dll)

NuGet Gallery | BouncyCastle.Crypto.dll 1.8.1

C#测试控制台应用程序

  1. using System;
  2. namespace TestAES_GCM_256
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. //Generate and dump KEY so we could use again
  9. //Console.WriteLine(AesGcm256.toHex(AesGcm256.NewKey()));
  10. //Generate and dump IV so we could use again
  11. //Console.WriteLine(AesGcm256.toHex(AesGcm256.NewIv()));
  12. //Console.ReadKey();
  13. //using above code these key and iv was generated
  14. string hexKey =
  15. "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
  16. string hexIV = "E1E592E87225847C11D948684F3B070D";
  17. string plainText = "Test encryption and decryption";
  18. Console.WriteLine("Plain Text: " + plainText);
  19. //encrypt - result base64 encoded string
  20. string encryptedText = AesGcm256.encrypt
  21. (plainText, AesGcm256.HexToByte(hexKey), AesGcm256.HexToByte(hexIV));
  22. Console.WriteLine("Encrypted base64 encoded: " + encryptedText);
  23. //decrypt - result plain string
  24. string decryptedText = AesGcm256.decrypt
  25. (encryptedText, AesGcm256.HexToByte(hexKey),
  26. AesGcm256.HexToByte(hexIV));
  27. Console.WriteLine("Decrypted Text: " + decryptedText);
  28. if (plainText.Equals(decryptedText))
  29. {
  30. Console.WriteLine("Test Passed");
  31. }
  32. else
  33. {
  34. Console.WriteLine("Test Failed");
  35. }
  36. /* Console Output
  37. Plain Text: Test encryption and decryption
  38. Encrypted base64 encoded:
  39. A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
  40. Decrypted Text: Test encryption and decryption
  41. Test Passed
  42. Press any key to continue . . .
  43. */
  44. }
  45. }
  46. }

C#加密/解密类

  1. using System;
  2. using System.Text;
  3. using Org.BouncyCastle.Crypto.Engines;
  4. using Org.BouncyCastle.Crypto.Modes;
  5. using Org.BouncyCastle.Crypto.Parameters;
  6. using Org.BouncyCastle.Security;
  7. namespace TestAES_GCM_256
  8. {
  9. public class AesGcm256
  10. {
  11. private static readonly SecureRandom Random = new SecureRandom();
  12. // Pre-configured Encryption Parameters
  13. public static readonly int NonceBitSize = 128;
  14. public static readonly int MacBitSize = 128;
  15. public static readonly int KeyBitSize = 256;
  16. private AesGcm256() { }
  17. public static byte[] NewKey()
  18. {
  19. var key = new byte[KeyBitSize / 8];
  20. Random.NextBytes(key);
  21. return key;
  22. }
  23. public static byte[] NewIv()
  24. {
  25. var iv = new byte[NonceBitSize / 8];
  26. Random.NextBytes(iv);
  27. return iv;
  28. }
  29. public static Byte[] HexToByte(string hexStr)
  30. {
  31. byte[] bArray = new byte[hexStr.Length / 2];
  32. for (int i = 0; i < (hexStr.Length / 2); i++)
  33. {
  34. byte firstNibble = Byte.Parse(hexStr.Substring((2 * i), 1),
  35. System.Globalization.NumberStyles.HexNumber); // [x,y)
  36. byte secondNibble = Byte.Parse(hexStr.Substring((2 * i) + 1, 1),
  37. System.Globalization.NumberStyles.HexNumber);
  38. int finalByte = (secondNibble) |
  39. (firstNibble << 4); // bit-operations
  40. // only with numbers,
  41. // not bytes.
  42. bArray[i] = (byte)finalByte;
  43. }
  44. return bArray;
  45. }
  46. public static string toHex(byte[] data)
  47. {
  48. string hex = string.Empty;
  49. foreach (byte c in data)
  50. {
  51. hex += c.ToString("X2");
  52. }
  53. return hex;
  54. }
  55. public static string toHex(string asciiString)
  56. {
  57. string hex = string.Empty;
  58. foreach (char c in asciiString)
  59. {
  60. int tmp = c;
  61. hex += string.Format
  62. ("{0:x2}", System.Convert.ToUInt32(tmp.ToString()));
  63. }
  64. return hex;
  65. }
  66. public static string encrypt(string PlainText, byte[] key, byte[] iv)
  67. {
  68. string sR = string.Empty;
  69. try
  70. {
  71. byte[] plainBytes = Encoding.UTF8.GetBytes(PlainText);
  72. GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
  73. AeadParameters parameters =
  74. new AeadParameters(new KeyParameter(key), 128, iv, null);
  75. cipher.Init(true, parameters);
  76. byte[] encryptedBytes =
  77. new byte[cipher.GetOutputSize(plainBytes.Length)];
  78. Int32 retLen = cipher.ProcessBytes
  79. (plainBytes, 0, plainBytes.Length, encryptedBytes, 0);
  80. cipher.DoFinal(encryptedBytes, retLen);
  81. sR = Convert.ToBase64String
  82. (encryptedBytes, Base64FormattingOptions.None);
  83. }
  84. catch (Exception ex)
  85. {
  86. Console.WriteLine(ex.Message);
  87. Console.WriteLine(ex.StackTrace);
  88. }
  89. return sR;
  90. }
  91. public static string decrypt(string EncryptedText, byte[] key, byte[] iv)
  92. {
  93. string sR = string.Empty;
  94. try
  95. {
  96. byte[] encryptedBytes = Convert.FromBase64String(EncryptedText);
  97. GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
  98. AeadParameters parameters =
  99. new AeadParameters(new KeyParameter(key), 128, iv, null);
  100. //ParametersWithIV parameters =
  101. //new ParametersWithIV(new KeyParameter(key), iv);
  102. cipher.Init(false, parameters);
  103. byte[] plainBytes =
  104. new byte[cipher.GetOutputSize(encryptedBytes.Length)];
  105. Int32 retLen = cipher.ProcessBytes
  106. (encryptedBytes, 0, encryptedBytes.Length, plainBytes, 0);
  107. cipher.DoFinal(plainBytes, retLen);
  108. sR = Encoding.UTF8.GetString(plainBytes).TrimEnd
  109. ("\r\n\0".ToCharArray());
  110. }
  111. catch (Exception ex)
  112. {
  113. Console.WriteLine(ex.Message);
  114. Console.WriteLine(ex.StackTrace);
  115. }
  116. return sR;
  117. }
  118. }
  119. }

对于Java

请将以下JAR添加到您的Java项目或类路径中:

bcprov-jdk15on-160.jar

Java测试控制台应用程序

  1. public class TestAes256GCM {
  2. public static void main(String[] args) {
  3. //Generate and dump KEY so we could use again
  4. //System.out.println(AesGcm256.toHex(AesGcm256.NewKey()));
  5. //Generate and dump IV so we could use again
  6. //System.out.println(AesGcm256.toHex(AesGcm256.NewIv()));
  7. //Console.ReadKey();
  8. //using above code these key and iv was generated
  9. String hexKey =
  10. "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
  11. String hexIV = "E1E592E87225847C11D948684F3B070D";
  12. String plainText = "Test encryption and decryption";
  13. System.out.println("Plain Text: " + plainText);
  14. //encrypt - result base64 encoded string
  15. String encryptedText = AesGcm256.encrypt
  16. (plainText, AesGcm256.HexToByte(hexKey), AesGcm256.HexToByte(hexIV));
  17. System.out.println("Encrypted base64 encoded: " + encryptedText);
  18. //decrypt - result plain string
  19. String decryptedText = AesGcm256.decrypt
  20. (encryptedText, AesGcm256.HexToByte(hexKey),
  21. AesGcm256.HexToByte(hexIV));
  22. System.out.println("Decrypted Text: " + decryptedText);
  23. if (plainText.equals(decryptedText))
  24. {
  25. System.out.println("Test Passed");
  26. }
  27. else
  28. {
  29. System.out.println("Test Failed");
  30. }
  31. /* Console Output
  32. Plain Text: Test encryption and decryption
  33. Encrypted base64 encoded:
  34. A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
  35. Decrypted Text: Test encryption and decryption
  36. Test Passed
  37. Press any key to continue . . .
  38. */
  39. }
  40. }

Java加密/解密类

  1. import java.io.UnsupportedEncodingException;
  2. import java.nio.charset.Charset;
  3. import java.security.SecureRandom;
  4. import java.util.Base64;
  5. import org.bouncycastle.crypto.DataLengthException;
  6. import org.bouncycastle.crypto.InvalidCipherTextException;
  7. import org.bouncycastle.crypto.engines.AESFastEngine;
  8. import org.bouncycastle.crypto.modes.GCMBlockCipher;
  9. import org.bouncycastle.crypto.params.AEADParameters;
  10. import org.bouncycastle.crypto.params.KeyParameter;
  11. public class AesGcm256 {
  12. private static final SecureRandom SECURE_RANDOM = new SecureRandom();
  13. // Pre-configured Encryption Parameters
  14. public static int NonceBitSize = 128;
  15. public static int MacBitSize = 128;
  16. public static int KeyBitSize = 256;
  17. private AesGcm256() {
  18. }
  19. public static byte[] NewKey() {
  20. byte[] key = new byte[KeyBitSize / 8];
  21. SECURE_RANDOM.nextBytes(key);
  22. return key;
  23. }
  24. public static byte[] NewIv() {
  25. byte[] iv = new byte[NonceBitSize / 8];
  26. SECURE_RANDOM.nextBytes(iv);
  27. return iv;
  28. }
  29. public static byte[] HexToByte(String hexStr) {
  30. int len = hexStr.length();
  31. byte[] data = new byte[len / 2];
  32. for (int i = 0; i < len; i += 2)
  33. {
  34. data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
  35. + Character.digit(hexStr.charAt(i + 1), 16));
  36. }
  37. return data;
  38. }
  39. public static String toHex(byte[] data) {
  40. final StringBuilder builder = new StringBuilder();
  41. for (byte b : data) {
  42. builder.append(Integer.toString(b, 16));
  43. }
  44. return builder.toString();
  45. }
  46. public static String encrypt(String PlainText, byte[] key, byte[] iv) {
  47. String sR = "";
  48. try {
  49. byte[] plainBytes = PlainText.getBytes("UTF-8");
  50. GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
  51. AEADParameters parameters =
  52. new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
  53. cipher.init(true, parameters);
  54. byte[] encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
  55. int retLen = cipher.processBytes
  56. (plainBytes, 0, plainBytes.length, encryptedBytes, 0);
  57. cipher.doFinal(encryptedBytes, retLen);
  58. sR = Base64.getEncoder().encodeToString(encryptedBytes);
  59. } catch (UnsupportedEncodingException | IllegalArgumentException |
  60. IllegalStateException | DataLengthException |
  61. InvalidCipherTextException ex) {
  62. System.out.println(ex.getMessage());
  63. }
  64. return sR;
  65. }
  66. public static String decrypt(String EncryptedText, byte[] key, byte[] iv) {
  67. String sR = "";
  68. try {
  69. byte[] encryptedBytes = Base64.getDecoder().decode(EncryptedText);
  70. GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
  71. AEADParameters parameters =
  72. new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
  73. cipher.init(false, parameters);
  74. byte[] plainBytes = new byte[cipher.getOutputSize(encryptedBytes.length)];
  75. int retLen = cipher.processBytes
  76. (encryptedBytes, 0, encryptedBytes.length, plainBytes, 0);
  77. cipher.doFinal(plainBytes, retLen);
  78. sR = new String(plainBytes, Charset.forName("UTF-8"));
  79. } catch (IllegalArgumentException | IllegalStateException |
  80. DataLengthException | InvalidCipherTextException ex) {
  81. System.out.println(ex.getMessage());
  82. }
  83. return sR;
  84. }
  85. }

对于C++Windows

请在您的测试项目中包含Crypto++项目。

正确的包含和链接库路径:

C++测试控制台应用程序

  1. // TestAES_GCM_256_C.cpp : Defines the entry point for the console application.
  2. //
  3. #pragma once
  4. #include "stdafx.h"
  5. #ifndef _CRT_SECURE_NO_DEPRECATE
  6. #define _CRT_SECURE_NO_DEPRECATE 1
  7. #endif
  8. #ifndef CRYPTOPP_DEFAULT_NO_DLL
  9. #define CRYPTOPP_DEFAULT_NO_DLL 1
  10. #endif
  11. #ifndef CRYPTOPP_ENABLE_NAMESPACE_WEAK
  12. #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
  13. #endif
  14. #ifdef _DEBUG
  15. #ifndef x64
  16. #pragma comment(lib, "./../../../common/Crypto5.6.1/Win32/Output/Debug/cryptlib.lib")
  17. #else
  18. #pragma comment(lib, "./../../../common/Crypto5.6.1/x64/Output/Debug/cryptlib.lib")
  19. #endif
  20. #else
  21. #ifndef x64
  22. #pragma comment(lib, "./../../../common/Crypto5.6.1/Win32/Output/Release/cryptlib.lib")
  23. #else
  24. #pragma comment(lib, "./../../../common/Crypto5.6.1/x64/Output/Release/cryptlib.lib")
  25. #endif
  26. #endif
  27. // Crypto++ Include
  28. #include "./../../../common/Crypto5.6.1/pch.h"
  29. #include "./../../../common/Crypto5.6.1/files.h"
  30. #include "./../../../common/Crypto5.6.1/default.h"
  31. #include "./../../../common/Crypto5.6.1/base64.h"
  32. #include "./../../../common/Crypto5.6.1/osrng.h"
  33. //AES
  34. #include "./../../../common/Crypto5.6.1/hex.h"
  35. using CryptoPP::HexEncoder;
  36. using CryptoPP::HexDecoder;
  37. #include "./../../../common/Crypto5.6.1/cryptlib.h"
  38. using CryptoPP::BufferedTransformation;
  39. using CryptoPP::AuthenticatedSymmetricCipher;
  40. #include "./../../../common/Crypto5.6.1/filters.h"
  41. using CryptoPP::StringSink;
  42. using CryptoPP::StringSource;
  43. using CryptoPP::AuthenticatedEncryptionFilter;
  44. using CryptoPP::AuthenticatedDecryptionFilter;
  45. #include "./../../../common/Crypto5.6.1/aes.h"
  46. using CryptoPP::AES;
  47. #include "./../../../common/Crypto5.6.1/gcm.h"
  48. using CryptoPP::GCM;
  49. using CryptoPP::GCM_TablesOption;
  50. #include <iostream>
  51. #include <string>
  52. USING_NAMESPACE(CryptoPP)
  53. USING_NAMESPACE(std)
  54. static inline RandomNumberGenerator& PSRNG(void);
  55. static inline RandomNumberGenerator& PSRNG(void)
  56. {
  57. static AutoSeededRandomPool rng;
  58. rng.Reseed();
  59. return rng;
  60. }
  61. bool encrypt_aes256_gcm(const char *aesKey, const char *aesIV,
  62. const char *inPlainText, char **outEncryptedBase64,
  63. int &dataLength);
  64. bool decrypt_aes256_gcm(const char *aesKey, const char *aesIV,
  65. const char *inBase64Text, char **outDecrypted, int &dataLength);
  66. void Base64Decode(const std::string &inString, std::string &outString);
  67. void HexDecode(const std::string &inString, std::string &outString);
  68. static std::string m_ErrorMessage;
  69. int main()
  70. {
  71. //using above code these key and iv was generated
  72. std::string hexKey =
  73. "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
  74. std::string hexDecodedKey;
  75. HexDecode(hexKey, hexDecodedKey);
  76. std::string hexIV = "E1E592E87225847C11D948684F3B070D";
  77. std::string hexDecodedIv;
  78. HexDecode(hexIV, hexDecodedIv);
  79. std::string plainText = "Test encryption and decryption";
  80. std::string encryptedWithJava =
  81. "A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==";
  82. printf("%s%s\n", "Plain Text: " , plainText.c_str());
  83. //encrypt - result base64 encoded string
  84. char *outEncryptedText=NULL;
  85. int outDataLength=0;
  86. bool bR = encrypt_aes256_gcm(hexDecodedKey.c_str(),
  87. hexDecodedIv.c_str(), plainText.c_str(),
  88. &outEncryptedText, outDataLength);
  89. printf("%s%s\n", "Encrypted base64 encoded: " , outEncryptedText);
  90. //decrypt - result plain string
  91. char* outDecryptedText=NULL;
  92. int outDecryptedDataLength=0;
  93. bR = decrypt_aes256_gcm(hexDecodedKey.c_str(),
  94. hexDecodedIv.c_str(), encryptedWithJava.c_str(),
  95. &outDecryptedText, outDecryptedDataLength);
  96. printf("%s%s\n", "Decrypted Text Encrypted by Java: " , outDecryptedText);
  97. if (plainText == outDecryptedText)
  98. {
  99. printf("%s\n", "Test Passed");
  100. }
  101. else
  102. {
  103. printf("%s\n", "Test Failed");
  104. }
  105. return 0;
  106. }
  107. bool encrypt_aes256_gcm(const char *aesKey, const char *aesIV,
  108. const char *inPlainText,
  109. char **outEncryptedBase64, int &dataLength)
  110. {
  111. bool bR = false;
  112. //const int TAG_SIZE = 12;
  113. std::string outText;
  114. std::string outBase64;
  115. if (strlen(aesKey)>31 && strlen(aesIV)>15)
  116. {
  117. try
  118. {
  119. GCM< AES >::Encryption aesEncryption;
  120. aesEncryption.SetKeyWithIV(reinterpret_cast<const byte*>(aesKey),
  121. AES::MAX_KEYLENGTH, reinterpret_cast<const byte*>(aesIV), AES::BLOCKSIZE);
  122. StringSource(inPlainText, true, new AuthenticatedEncryptionFilter
  123. (aesEncryption, new StringSink(outText)
  124. ) // AuthenticatedEncryptionFilter
  125. ); // StringSource
  126. CryptoPP::Base64Encoder *base64Encoder = new CryptoPP::Base64Encoder
  127. (new StringSink(outBase64), false);
  128. base64Encoder->PutMessageEnd(reinterpret_cast<const char=""
  129. unsigned=""> (outText.data()), outText.length());
  130. delete base64Encoder;
  131. dataLength = outBase64.length();
  132. if (outBase64.length()>0)
  133. {
  134. if (*outEncryptedBase64) free(*outEncryptedBase64);
  135. *outEncryptedBase64 = (char*)malloc(dataLength + 1);
  136. memset(*outEncryptedBase64, '\0', dataLength + 1);
  137. memcpy(*outEncryptedBase64, outBase64.c_str(), dataLength);
  138. bR = true;
  139. }
  140. else
  141. {
  142. m_ErrorMessage.append("Encryption Failed");
  143. }
  144. }
  145. catch (CryptoPP::InvalidArgument& e)
  146. {
  147. m_ErrorMessage.append(e.what());
  148. }
  149. catch (CryptoPP::Exception& e)
  150. {
  151. m_ErrorMessage.append(e.what());
  152. }
  153. }
  154. else
  155. {
  156. m_ErrorMessage.append("AES Key or IV cannot be empty");
  157. }
  158. outText.clear();
  159. outBase64.clear();
  160. return bR;
  161. }
  162. bool decrypt_aes256_gcm(const char *aesKey, const char *aesIV,
  163. const char *inBase64Text, char **outDecrypted, int &dataLength)
  164. {
  165. bool bR = false;
  166. std::string outText;
  167. std::string pszDecodedText;
  168. Base64Decode(inBase64Text, pszDecodedText);
  169. if (strlen(aesKey)>31 && strlen(aesIV)>15)
  170. {
  171. try
  172. {
  173. GCM< AES >::Decryption aesDecryption;
  174. aesDecryption.SetKeyWithIV(reinterpret_cast<const byte*>(aesKey),
  175. AES::MAX_KEYLENGTH,
  176. reinterpret_cast<const byte*>(aesIV), AES::BLOCKSIZE);
  177. AuthenticatedDecryptionFilter df(aesDecryption, new StringSink(outText));
  178. StringSource(pszDecodedText, true,
  179. new Redirector(df /*, PASS_EVERYTHING */)
  180. ); // StringSource
  181. bR = df.GetLastResult();
  182. dataLength = outText.length();
  183. if (outText.length()>0)
  184. {
  185. if (*outDecrypted) free(*outDecrypted);
  186. *outDecrypted = (char*)malloc(dataLength + 1);
  187. memset(*outDecrypted, '\0', dataLength + 1);
  188. memcpy(*outDecrypted, outText.c_str(), dataLength);
  189. bR = true;
  190. }
  191. else
  192. {
  193. m_ErrorMessage.append("Decryption Failed");
  194. }
  195. }
  196. catch (CryptoPP::HashVerificationFilter::HashVerificationFailed& e)
  197. {
  198. m_ErrorMessage.append(e.what());
  199. }
  200. catch (CryptoPP::InvalidArgument& e)
  201. {
  202. m_ErrorMessage.append(e.what());
  203. }
  204. catch (CryptoPP::Exception& e)
  205. {
  206. m_ErrorMessage.append(e.what());
  207. }
  208. }
  209. else
  210. {
  211. m_ErrorMessage.append("AES Key or IV cannot be empty");
  212. }
  213. return bR;
  214. }
  215. void Base64Decode(const std::string &inString, std::string &outString)
  216. {
  217. StringSource(inString, true, new Base64Decoder(new StringSink(outString)));
  218. }
  219. void HexDecode(const std::string &inString, std::string &outString)
  220. {
  221. StringSource(inString, true, new HexDecoder(new StringSink(outString)));
  222. }

Linux库(GNU C++ 14标准)

此存储库包含此处的2Apache Netbeans项目。请克隆存储库并在 Netbeans IDE中打开项目。您必须已配置Netbeans IDE才能编辑C++项目。

构建步骤

crypto++

要构建,请在终端中打开 cryptopp870 文件夹并输入 make 命令。它将构建 libcryptopp.a 静态库。该库默认为OS体系结构。GcmAesGcmAesNetbeans 项目依赖于 libcryptopp.a 并链接到它。

库可用后,可以从 Netbeans IDE 单独构建这两个项目。GcmAesTest项目具有libGcmAes.so依赖,并且将预先构建。构建后,也可以调试项目。

测试程序验证少量加密和解密测试。其中之一是解密使用Java代码加密的文本(链接如下)。

它生成以下示例测试结果:

  1. Key=D303E8441BE72DD1501319D64A46CA6442031A29706000D2D3988175D7B492C4
  2. Len=64
  3. IV=D4AF4DB97D31492CA227D7BBB59AC494
  4. Len=32
  5. Key and IV Test OK
  6. Test 1 -> Encrypted base64 encoded:
  7. G3Elmv9n3cRyvVl5gZHtne9AEQHM3agHU1KTMvFxhSdWyASx5fD9uVfhVk+KRA==
  8. Test 1 -> Decrypted: Test encryption and decryption
  9. Test 1 -> Encryption / Decryption OK
  10. Plain Text: Test encryption and decryption
  11. Test 2 -> Encrypted base64 encoded:
  12. A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
  13. Test 2 -> Decrypted: Test encryption and decryption
  14. Test 2 -> Encryption / Decryption OK
  15. Test 3 -> Decrypted: Test encryption and decryption
  16. Test 3 -> Java Encrypted / C++ Decryption OK
  17. Test 4 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
  18. Test 4 -> Hex Encoded:
  19. 73796C6C61626963206B616E6120E28093206869726167616E612028E5B9B3E4BBAEE5908D2920616E64206B6174616B616E612028E78987E4BBAEE5908D29
  20. Test 4 -> Hex Encoding OK
  21. Test 5 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
  22. Test 5 -> Hex Decoded: syllabic kana – hiragana (平仮名) and katakana (片仮名)
  23. Test 5 -> Hex Decoding OK
  24. Test 6 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
  25. Test 6 -> Base64 Encoded:
  26. c3lsbGFiaWMga2FuYSDigJMgaGlyYWdhbmEgKOW5s+S7ruWQjSkgYW5kIGthdGFrYW5hICjniYfku67lkI0p
  27. Test 6 -> Base64 Encoding OK
  28. Test 7 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
  29. Test 7 -> Base64 Decoded: syllabic kana – hiragana (平仮名) and katakana (片仮名)
  30. Test 7 -> Base64 Decoding OK

该测试项目还演示了如何将 libGcmAes.so Linux等系统上的其他C++项目一起使用。通常,只需将 GcmAes.h 包含在您的项目中,并且必须将您的项目与 libGcmAes.so 链接。代码使用 C++ 14 标准。

GcmAes.h

  1. /*
  2. Copyright (©) 2023 Kashif Mushtaq
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in all
  10. copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. SOFTWARE.
  18. */
  19. #ifndef __CRYPTOGRAPHER_INCLUDE_HEADER__
  20. #define __CRYPTOGRAPHER_INCLUDE_HEADER__
  21. #pragma once
  22. #include <iostream>
  23. #include <string>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <iostream>
  27. #include <fstream>
  28. #include <cstdlib>
  29. #include <syslog.h>
  30. #include <stdarg.h>
  31. #include <fcntl.h>
  32. #include <unistd.h>
  33. #include <signal.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <errno.h>
  37. /**
  38. Exported for dynamic loading and calling
  39. */
  40. #ifdef __cplusplus
  41. extern "C" {
  42. #endif
  43. /*
  44. * Note:
  45. * All functions returning buffers like **out<name>
  46. * are allocated using new and are null terminated.
  47. * Users must clear them using delete *out<name>
  48. */
  49. // ------------------------------ libGcmAes.so Exports ---------------------------
  50. bool _base64Encode(/*[in]*/ const char *inPlainText,
  51. /*[out]*/ char **outBase64Encoded, /*[in, out]*/ int &dataLength);
  52. bool _base64Decode(/*[in]*/ const char *inBase64Text,
  53. /*[out]*/ char **outPlainText, /*[in, out]*/ int &dataLength);
  54. bool _hexDecode(/*[in]*/ const char *inHexEncodedText,
  55. /*[out]*/ char **outHexDecoded);
  56. bool _hexEncode(/*[in]*/ const char *inData, /*[out]*/ char **outHexEncoded);
  57. bool _encrypt_GcmAes256(/*[in]*/const char *inHexKey,
  58. /*[in]*/const char *inHexIv, /*[in]*/const char *inPlainText,
  59. /*[out]*/ char **outEncryptedBase64, /*[in, out]*/int &dataLength);
  60. bool _decrypt_GcmAes256(/*[in]*/const char *inHexKey,
  61. /*[in]*/const char *inHexIv, /*[in]*/const char *inBase64Text,
  62. /*[out]*/ char **outDecrypted, /*[in, out]*/int &dataLength);
  63. bool _getNewAESKeyAndIv(/*[out]*/ char **outHexKey,
  64. /*[out]*/ char **outHexIv, /*[in, out]*/int &outKeyLength,
  65. /*[in, out]*/ int &outIvLength);
  66. // ------------------------------ libGcmAes.so Exports ---------------------------
  67. #ifdef __cplusplus
  68. }
  69. #endif
  70. #endif

测试程序

  1. /*
  2. Copyright (©) 2023 Kashif Mushtaq
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in all
  10. copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. SOFTWARE.
  18. */
  19. /*
  20. * File: main.cpp
  21. * Author: kmushtaq
  22. *
  23. * Created on April 11, 2023, 9:21 AM
  24. */
  25. //Include GcmAES header and link this project against libGcmAes.so
  26. #include "GcmAes.h"
  27. #include <cstdlib>
  28. #include <regex>
  29. #include <cstring>
  30. using namespace std;
  31. /*
  32. *
  33. */
  34. int main(int argc, char** argv)
  35. {
  36. // lets first generate encryption Key and IV for AES 256 GCM.
  37. // Key size is 32 bytes and IV size is 16 bytes
  38. // Lib generated Key and IV are hex encoded.
  39. // Encryption and decryption function expects hex encoded Key and IV.
  40. std::string inHexKey;
  41. std::string inHexIV;
  42. char* pszKey = nullptr;
  43. char* pszIv = nullptr;
  44. int keyLen = 0;
  45. int ivLen = 0;
  46. std::string plainText = "Test encryption and decryption";
  47. bool result = false;
  48. /* ----------------------- Key Generation Test ----------------------- */
  49. result = _getNewAESKeyAndIv(&pszKey, &pszIv, keyLen, ivLen);
  50. if (result)
  51. {
  52. printf("Key=%s\nLen=%i\n\nIV=%s\nLen=%i\n", pszKey, keyLen, pszIv, ivLen);
  53. printf("Key and IV Test OK\n\n");
  54. }
  55. else
  56. {
  57. printf("%s", "Key and IV generation failed. Please check syslog for errors");
  58. return 1;
  59. }
  60. /* ----------------------- Key Generation Test ----------------------- */
  61. /* ----------------------- Encryption Decryption Test ----------------------- */
  62. //Save key and IV to call encryption and decryption functions
  63. inHexKey = pszKey;
  64. inHexIV = pszIv;
  65. char* outTestEncrypted = nullptr;
  66. int outTestEncryptedLen = 0;
  67. //encrypt - result base64 encoded
  68. result = _encrypt_GcmAes256(inHexKey.c_str(), inHexIV.c_str(),
  69. plainText.c_str(), &outTestEncrypted, outTestEncryptedLen);
  70. if (result)
  71. {
  72. printf("Test 1 -> Encrypted base64 encoded: %s\n", outTestEncrypted);
  73. }
  74. else
  75. {
  76. printf("%s", "Test 1 -> Encryption failed. Please check syslog for errors");
  77. return 1;
  78. }
  79. char* outTestDecrypted = nullptr;
  80. int outTestDecryptedLen = 0;
  81. //decrypt - result plain text
  82. result = _decrypt_GcmAes256(inHexKey.c_str(), inHexIV.c_str(),
  83. outTestEncrypted, &outTestDecrypted, outTestDecryptedLen);
  84. if (result && strcmp(plainText.c_str(), outTestDecrypted) == 0)
  85. {
  86. printf("Test 1 -> Decrypted: %s\n", outTestDecrypted);
  87. printf("Test 1 -> Encryption / Decryption OK\n\n");
  88. }
  89. else
  90. {
  91. printf("%s", "Test 1 -> Decryption failed. Please check syslog for errors");
  92. return 1;
  93. }
  94. inHexKey.clear();
  95. inHexIV.clear();
  96. //clear buffers
  97. if (outTestEncrypted) delete outTestEncrypted;
  98. outTestEncrypted = nullptr;
  99. if (outTestDecrypted) delete outTestDecrypted;
  100. outTestDecrypted = nullptr;
  101. //clear buffers allocated by _getNewAESKeyAndIv function
  102. if (pszKey) delete pszKey;
  103. pszKey = nullptr;
  104. if (pszIv) delete pszIv;
  105. pszIv = nullptr;
  106. /* ------------------ Encryption Decryption Test ----------------------- */
  107. /* ------------------ C++ Encryption and C++ Decryption Test ------------------ */
  108. std::string hexKey =
  109. "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
  110. std::string hexIV = "E1E592E87225847C11D948684F3B070D";
  111. printf("Plain Text: %s\n", plainText.c_str());
  112. char* outEncrypted = nullptr;
  113. int outEncryptedLen = 0;
  114. //encrypt - result base64 encoded
  115. result = _encrypt_GcmAes256(hexKey.c_str(), hexIV.c_str(),
  116. plainText.c_str(), &outEncrypted, outEncryptedLen);
  117. if (result)
  118. {
  119. printf("Test 2 -> Encrypted base64 encoded: %s\n", outEncrypted);
  120. }
  121. else
  122. {
  123. printf("%s", "Test 2 -> Encryption failed. Please check syslog for errors");
  124. return 1;
  125. }
  126. char* outDecrypted = nullptr;
  127. int outDecryptedLen = 0;
  128. //decrypt - result plain text
  129. result = _decrypt_GcmAes256(hexKey.c_str(),
  130. hexIV.c_str(), outEncrypted, &outDecrypted, outDecryptedLen);
  131. if (result && strcmp(plainText.c_str(), outDecrypted) == 0)
  132. {
  133. printf("Test 2 -> Decrypted: %s\n", outDecrypted);
  134. printf("Test 2 -> Encryption / Decryption OK\n\n");
  135. }
  136. else
  137. {
  138. printf("%s", "Test 2 -> Decryption failed. Please check syslog for errors");
  139. return 1;
  140. }
  141. //clear buffers
  142. if (outEncrypted) delete outEncrypted;
  143. outEncrypted = nullptr;
  144. if (outDecrypted) delete outDecrypted;
  145. outDecrypted = nullptr;
  146. /* ------------------ C++ Encryption and C++ Decryption Test ------------------ */
  147. /* ------------------ Java based Encryption and C++ Decryption Test ----------- */
  148. //Java Encrypted with same Key and IV as above
  149. // A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
  150. std::string javaEncrypted =
  151. "A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==";
  152. char* outCDecrypted;
  153. int outCDecryptedLen = 0;
  154. //decrypt - result plain text
  155. result = _decrypt_GcmAes256(hexKey.c_str(), hexIV.c_str(),
  156. javaEncrypted.c_str(), &outCDecrypted, outCDecryptedLen);
  157. if (result && strcmp(plainText.c_str(), outCDecrypted) == 0)
  158. {
  159. printf("Test 3 -> Decrypted: %s\n", outCDecrypted);
  160. printf("Test 3 -> Java Encrypted / C++ Decryption OK\n\n");
  161. }
  162. else
  163. {
  164. printf("%s", "Test 3 -> Java Decryption failed.
  165. Please check syslog for errors");
  166. return 1;
  167. }
  168. //clear buffers
  169. if (outCDecrypted) delete outCDecrypted;
  170. outCDecrypted = nullptr;
  171. /* ---------------- Java based Encryption and C++ Decryption Test --------------- */
  172. /*
  173. Result:
  174. Key=BF2F0CEC3D78EEB8388D8A78402510B9F3A99F7F69E98C6DB7168D0C57270EF4
  175. Len=64
  176. IV=FE6A26A45DB769F02C55CF12252F8A32
  177. Len=32
  178. Key and IV Test OK
  179. Test 1 -> Encrypted base64 encoded:
  180. 5NKdId7ZkBMWTtM5OhtPiaq1x0lBhbUSCxpcWK8PjjIGUvVdMdYET0Gw1mwmOw==
  181. Test 1 -> Decrypted: Test encryption and decryption
  182. Test 1 -> Encryption / Decryption OK
  183. Plain Text: Test encryption and decryptionTest 2 ->
  184. Encrypted base64 encoded: A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
  185. Test 2 -> Decrypted: Test encryption and decryption
  186. Test 2 -> Encryption / Decryption OK
  187. Test 3 -> Decrypted: Test encryption and decryption
  188. Test 3 -> Java Encrypted / C++ Decryption OK
  189. RUN FINISHED; exit value 0; real time: 20ms; user: 0ms; system: 0ms
  190. */
  191. /* ----------------------- Hex Encoding / Decoding Test ----------------------- */
  192. std::string pszPlainText = "syllabic kana – hiragana (平仮名) and katakana (片仮名)";
  193. char* hexEncoded = nullptr;
  194. char* hexDecoded = nullptr;
  195. result = _hexEncode(pszPlainText.c_str(), &hexEncoded);
  196. if(result)
  197. {
  198. printf("Test 4 -> Multi-byte Text: %s\n", pszPlainText.c_str());
  199. printf("Test 4 -> Hex Encoded: %s\n", hexEncoded);
  200. printf("Test 4 -> Hex Encoding OK\n\n");
  201. }
  202. else
  203. {
  204. printf("%s", "Test 4 -> Encoding failed.");
  205. return 1;
  206. }
  207. result = _hexDecode(hexEncoded, &hexDecoded);
  208. if(result && strcmp(pszPlainText.c_str(), hexDecoded) == 0)
  209. {
  210. printf("Test 5 -> Multi-byte Text: %s\n", pszPlainText.c_str());
  211. printf("Test 5 -> Hex Decoded: %s\n", hexDecoded);
  212. printf("Test 5 -> Hex Decoding OK\n\n");
  213. }
  214. else
  215. {
  216. printf("%s", "Test 4 -> Decoding failed.");
  217. return 1;
  218. }
  219. if(hexEncoded) delete hexEncoded;
  220. if(hexDecoded) delete hexDecoded;
  221. hexEncoded = nullptr;
  222. hexDecoded = nullptr;
  223. /* ----------------------- Hex Encoding / Decoding Test ----------------------- */
  224. /* ----------------------- Base64 Encoding / Decoding Test -------------------- */
  225. char* base64Encoded = nullptr;
  226. char* base64Decoded = nullptr;
  227. int base64Len = pszPlainText.length();
  228. result = _base64Encode(pszPlainText.c_str(), &base64Encoded, base64Len);
  229. if(result)
  230. {
  231. printf("Test 6 -> Multi-byte Text: %s\n", pszPlainText.c_str());
  232. printf("Test 6 -> Base64 Encoded: %s\n", base64Encoded);
  233. printf("Test 6 -> Base64 Encoding OK\n\n");
  234. }
  235. else
  236. {
  237. printf("%s", "Test 6 -> Encoding failed.");
  238. return 1;
  239. }
  240. base64Len = strlen(base64Encoded);
  241. result = _base64Decode(base64Encoded, &base64Decoded, base64Len);
  242. if(result && strcmp(pszPlainText.c_str(), base64Decoded) == 0)
  243. {
  244. printf("Test 7 -> Multi-byte Text: %s\n", pszPlainText.c_str());
  245. printf("Test 7 -> Base64 Decoded: %s\n", base64Decoded);
  246. printf("Test 7 -> Base64 Decoding OK\n\n");
  247. }
  248. else
  249. {
  250. printf("%s", "Test 7 -> Decoding failed.");
  251. return 1;
  252. }
  253. if(base64Encoded) delete base64Encoded;
  254. if(base64Decoded) delete base64Decoded;
  255. base64Encoded = nullptr;
  256. base64Decoded = nullptr;
  257. /* ----------------------- Base64 Encoding / Decoding Test -------------------- */
  258. hexKey.clear();
  259. hexIV.clear();
  260. pszPlainText.clear();
  261. return 0;
  262. }

Windows x64 C++ DLL

项目完全涵盖了上述Linux lib项目的所有功能、测试和用例。
请访问 GitHub上的Windows C++ x64 DLL和示例测试程序

使用libGcmAes.soNodeC#.Net Core)包装器

两个项目提供包装类和测试项目,用于调用 libGcmAes.so 与加密和解密相关的导出函数。Docker容器(Linux x64)可以使用这些包装器来实现AES 256 GCM跨平台加密和解密。
请访问GitHub上的 NodeJS和.Net Core Wrappers

https://www.codeproject.com/Articles/1265115/Cross-Platform-AES-256-GCM-Encryption-Decryption

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号