赞
踩
目录
使用libGcmAes.so的Node和C#(.Net Core)包装器
本文的目的是为需要在多个平台上进行最强加密的项目提供一个起点。此处以及C++(Windows和Linux)、Java和C#的GitHub存储库中提供了示例代码。最近,一个基于Linux的动态库和一个解释如何使用它的测试程序被上传到GitHub。Linux x64上的C++意味着它也可以用于NodeJS,只需创建一个包装器。同样,它也可以很容易地在苹果机器上使用。
在安全、身份管理和数据保护领域工作了一段时间后,我在公共领域发现了极少数基于AES 256 GCM算法的跨平台加密工作示例。这与Google在访问Gmail等时使用的算法相同。
本文可以帮助您实现非常强大的跨平台加密/解密。示例代码使用C++、C#和Java。但是,通过JNI(Java本机接口)的Java和通过COM的C#可以调用本机C++代码,在我的测试中,与纯Java或C#实现相比,这似乎要快得多。不过,有时人们希望在不调用本机C++层的情况下执行此操作。
对于C#,为了实现AES 256 GCM加密,我使用了Bouncy Castle加密库。本文提供的代码片段非常适合跨各种平台的加密和解密。我测试了它在Linux(使用Mono框架)和Windows上运行。
对于C++层,我使用了Crypto++。该库是跨平台兼容的(Windows、Linux 和其他库,如Solaris等)。Crypto++是一个健壮且实现良好的开源加密库。
本文不适合初学者,也不打算教授AES GCM算法。
本文为您提供了一个示例代码,以便通过您自己的修改来实现。
C++有点复杂。下载Crypto++源代码。创建一个控制台项目,并将现有Crypto++项目添加到解决方案中。然后,将控制台项目设置为启动项目,并设置生成依赖项顺序。
从文章中复制粘贴代码并更正头文件路径(如 pch.h)您也可以在项目属性中添加源代码目录以修复路径。同样,您可以更正Crypto++编译库的路径或将其添加到您的项目属性中。
本文的另一个目的是将所有三种主要的编程语言示例代码组合在一个地方。您不必搜索数千个单独的样本,其中一些样本无法按预期工作。此处的代码示例可以正常工作。
最近,一个基于Linux的动态库和一个解释如何使用它的测试程序被上传到GitHub。Linux x64上的C++意味着它也可以用于NodeJS,只需创建一个包装器。同样,它也可以很容易地在苹果机器上使用。
跨平台AES 256 GCM加密和解密(C++、C#和Java)
您还可以在此处和此处阅读有关Crypto++ AES GCM实现或算法本身的更多信息。
同样,可以在此处找到有关BouncyCastle的详细信息。
C#代码中使用的BouncyCastle .NET在这里。
请添加参考:
BouncyCastle.Crypto (BouncyCastle.Crypto.dll)
NuGet Gallery | BouncyCastle.Crypto.dll 1.8.1
- using System;
- namespace TestAES_GCM_256
- {
- class Program
- {
- static void Main(string[] args)
- {
- //Generate and dump KEY so we could use again
- //Console.WriteLine(AesGcm256.toHex(AesGcm256.NewKey()));
-
- //Generate and dump IV so we could use again
- //Console.WriteLine(AesGcm256.toHex(AesGcm256.NewIv()));
-
- //Console.ReadKey();
-
- //using above code these key and iv was generated
- string hexKey =
- "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
- string hexIV = "E1E592E87225847C11D948684F3B070D";
-
- string plainText = "Test encryption and decryption";
- Console.WriteLine("Plain Text: " + plainText);
-
- //encrypt - result base64 encoded string
- string encryptedText = AesGcm256.encrypt
- (plainText, AesGcm256.HexToByte(hexKey), AesGcm256.HexToByte(hexIV));
- Console.WriteLine("Encrypted base64 encoded: " + encryptedText);
-
- //decrypt - result plain string
- string decryptedText = AesGcm256.decrypt
- (encryptedText, AesGcm256.HexToByte(hexKey),
- AesGcm256.HexToByte(hexIV));
- Console.WriteLine("Decrypted Text: " + decryptedText);
-
- if (plainText.Equals(decryptedText))
- {
- Console.WriteLine("Test Passed");
- }
- else
- {
- Console.WriteLine("Test Failed");
- }
-
- /* Console Output
- Plain Text: Test encryption and decryption
- Encrypted base64 encoded:
- A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
- Decrypted Text: Test encryption and decryption
- Test Passed
- Press any key to continue . . .
- */
- }
- }
- }
- using System;
- using System.Text;
- using Org.BouncyCastle.Crypto.Engines;
- using Org.BouncyCastle.Crypto.Modes;
- using Org.BouncyCastle.Crypto.Parameters;
- using Org.BouncyCastle.Security;
-
- namespace TestAES_GCM_256
- {
- public class AesGcm256
- {
- private static readonly SecureRandom Random = new SecureRandom();
-
- // Pre-configured Encryption Parameters
- public static readonly int NonceBitSize = 128;
- public static readonly int MacBitSize = 128;
- public static readonly int KeyBitSize = 256;
-
- private AesGcm256() { }
-
- public static byte[] NewKey()
- {
- var key = new byte[KeyBitSize / 8];
- Random.NextBytes(key);
- return key;
- }
-
- public static byte[] NewIv()
- {
- var iv = new byte[NonceBitSize / 8];
- Random.NextBytes(iv);
- return iv;
- }
-
- public static Byte[] HexToByte(string hexStr)
- {
- byte[] bArray = new byte[hexStr.Length / 2];
- for (int i = 0; i < (hexStr.Length / 2); i++)
- {
- byte firstNibble = Byte.Parse(hexStr.Substring((2 * i), 1),
- System.Globalization.NumberStyles.HexNumber); // [x,y)
- byte secondNibble = Byte.Parse(hexStr.Substring((2 * i) + 1, 1),
- System.Globalization.NumberStyles.HexNumber);
- int finalByte = (secondNibble) |
- (firstNibble << 4); // bit-operations
- // only with numbers,
- // not bytes.
- bArray[i] = (byte)finalByte;
- }
- return bArray;
- }
-
- public static string toHex(byte[] data)
- {
- string hex = string.Empty;
- foreach (byte c in data)
- {
- hex += c.ToString("X2");
- }
- return hex;
- }
-
- public static string toHex(string asciiString)
- {
- string hex = string.Empty;
- foreach (char c in asciiString)
- {
- int tmp = c;
- hex += string.Format
- ("{0:x2}", System.Convert.ToUInt32(tmp.ToString()));
- }
- return hex;
- }
-
- public static string encrypt(string PlainText, byte[] key, byte[] iv)
- {
- string sR = string.Empty;
- try
- {
- byte[] plainBytes = Encoding.UTF8.GetBytes(PlainText);
-
- GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
- AeadParameters parameters =
- new AeadParameters(new KeyParameter(key), 128, iv, null);
-
- cipher.Init(true, parameters);
-
- byte[] encryptedBytes =
- new byte[cipher.GetOutputSize(plainBytes.Length)];
- Int32 retLen = cipher.ProcessBytes
- (plainBytes, 0, plainBytes.Length, encryptedBytes, 0);
- cipher.DoFinal(encryptedBytes, retLen);
- sR = Convert.ToBase64String
- (encryptedBytes, Base64FormattingOptions.None);
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- Console.WriteLine(ex.StackTrace);
- }
-
- return sR;
- }
-
- public static string decrypt(string EncryptedText, byte[] key, byte[] iv)
- {
- string sR = string.Empty;
- try
- {
- byte[] encryptedBytes = Convert.FromBase64String(EncryptedText);
-
- GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
- AeadParameters parameters =
- new AeadParameters(new KeyParameter(key), 128, iv, null);
- //ParametersWithIV parameters =
- //new ParametersWithIV(new KeyParameter(key), iv);
-
- cipher.Init(false, parameters);
- byte[] plainBytes =
- new byte[cipher.GetOutputSize(encryptedBytes.Length)];
- Int32 retLen = cipher.ProcessBytes
- (encryptedBytes, 0, encryptedBytes.Length, plainBytes, 0);
- cipher.DoFinal(plainBytes, retLen);
-
- sR = Encoding.UTF8.GetString(plainBytes).TrimEnd
- ("\r\n\0".ToCharArray());
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- Console.WriteLine(ex.StackTrace);
- }
-
- return sR;
- }
- }
- }
请将以下JAR添加到您的Java项目或类路径中:
bcprov-jdk15on-160.jar
- public class TestAes256GCM {
-
- public static void main(String[] args) {
- //Generate and dump KEY so we could use again
- //System.out.println(AesGcm256.toHex(AesGcm256.NewKey()));
-
- //Generate and dump IV so we could use again
- //System.out.println(AesGcm256.toHex(AesGcm256.NewIv()));
-
- //Console.ReadKey();
-
- //using above code these key and iv was generated
- String hexKey =
- "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
- String hexIV = "E1E592E87225847C11D948684F3B070D";
-
- String plainText = "Test encryption and decryption";
- System.out.println("Plain Text: " + plainText);
-
- //encrypt - result base64 encoded string
- String encryptedText = AesGcm256.encrypt
- (plainText, AesGcm256.HexToByte(hexKey), AesGcm256.HexToByte(hexIV));
- System.out.println("Encrypted base64 encoded: " + encryptedText);
-
- //decrypt - result plain string
- String decryptedText = AesGcm256.decrypt
- (encryptedText, AesGcm256.HexToByte(hexKey),
- AesGcm256.HexToByte(hexIV));
- System.out.println("Decrypted Text: " + decryptedText);
-
- if (plainText.equals(decryptedText))
- {
- System.out.println("Test Passed");
- }
- else
- {
- System.out.println("Test Failed");
- }
-
- /* Console Output
- Plain Text: Test encryption and decryption
- Encrypted base64 encoded:
- A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
- Decrypted Text: Test encryption and decryption
- Test Passed
- Press any key to continue . . .
- */
- }
- }
- import java.io.UnsupportedEncodingException;
- import java.nio.charset.Charset;
- import java.security.SecureRandom;
- import java.util.Base64;
- import org.bouncycastle.crypto.DataLengthException;
- import org.bouncycastle.crypto.InvalidCipherTextException;
- import org.bouncycastle.crypto.engines.AESFastEngine;
- import org.bouncycastle.crypto.modes.GCMBlockCipher;
- import org.bouncycastle.crypto.params.AEADParameters;
- import org.bouncycastle.crypto.params.KeyParameter;
-
- public class AesGcm256 {
-
- private static final SecureRandom SECURE_RANDOM = new SecureRandom();
-
- // Pre-configured Encryption Parameters
- public static int NonceBitSize = 128;
- public static int MacBitSize = 128;
- public static int KeyBitSize = 256;
-
- private AesGcm256() {
- }
-
- public static byte[] NewKey() {
- byte[] key = new byte[KeyBitSize / 8];
- SECURE_RANDOM.nextBytes(key);
- return key;
- }
-
- public static byte[] NewIv() {
- byte[] iv = new byte[NonceBitSize / 8];
- SECURE_RANDOM.nextBytes(iv);
- return iv;
- }
-
- public static byte[] HexToByte(String hexStr) {
- int len = hexStr.length();
- byte[] data = new byte[len / 2];
- for (int i = 0; i < len; i += 2)
- {
- data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
- + Character.digit(hexStr.charAt(i + 1), 16));
- }
- return data;
- }
-
- public static String toHex(byte[] data) {
- final StringBuilder builder = new StringBuilder();
- for (byte b : data) {
- builder.append(Integer.toString(b, 16));
- }
- return builder.toString();
- }
-
- public static String encrypt(String PlainText, byte[] key, byte[] iv) {
- String sR = "";
- try {
- byte[] plainBytes = PlainText.getBytes("UTF-8");
-
- GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
- AEADParameters parameters =
- new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
-
- cipher.init(true, parameters);
-
- byte[] encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
- int retLen = cipher.processBytes
- (plainBytes, 0, plainBytes.length, encryptedBytes, 0);
- cipher.doFinal(encryptedBytes, retLen);
- sR = Base64.getEncoder().encodeToString(encryptedBytes);
- } catch (UnsupportedEncodingException | IllegalArgumentException |
- IllegalStateException | DataLengthException |
- InvalidCipherTextException ex) {
- System.out.println(ex.getMessage());
- }
-
- return sR;
- }
-
- public static String decrypt(String EncryptedText, byte[] key, byte[] iv) {
- String sR = "";
- try {
- byte[] encryptedBytes = Base64.getDecoder().decode(EncryptedText);
-
- GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
- AEADParameters parameters =
- new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
-
- cipher.init(false, parameters);
- byte[] plainBytes = new byte[cipher.getOutputSize(encryptedBytes.length)];
- int retLen = cipher.processBytes
- (encryptedBytes, 0, encryptedBytes.length, plainBytes, 0);
- cipher.doFinal(plainBytes, retLen);
-
- sR = new String(plainBytes, Charset.forName("UTF-8"));
- } catch (IllegalArgumentException | IllegalStateException |
- DataLengthException | InvalidCipherTextException ex) {
- System.out.println(ex.getMessage());
- }
-
- return sR;
- }
- }
请在您的测试项目中包含Crypto++项目。
正确的包含和链接库路径:
- // TestAES_GCM_256_C.cpp : Defines the entry point for the console application.
- //
-
- #pragma once
- #include "stdafx.h"
-
- #ifndef _CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_NO_DEPRECATE 1
- #endif
-
- #ifndef CRYPTOPP_DEFAULT_NO_DLL
- #define CRYPTOPP_DEFAULT_NO_DLL 1
- #endif
-
- #ifndef CRYPTOPP_ENABLE_NAMESPACE_WEAK
- #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
- #endif
-
- #ifdef _DEBUG
-
- #ifndef x64
- #pragma comment(lib, "./../../../common/Crypto5.6.1/Win32/Output/Debug/cryptlib.lib")
- #else
- #pragma comment(lib, "./../../../common/Crypto5.6.1/x64/Output/Debug/cryptlib.lib")
- #endif
- #else
- #ifndef x64
- #pragma comment(lib, "./../../../common/Crypto5.6.1/Win32/Output/Release/cryptlib.lib")
- #else
- #pragma comment(lib, "./../../../common/Crypto5.6.1/x64/Output/Release/cryptlib.lib")
- #endif
- #endif
-
- // Crypto++ Include
-
- #include "./../../../common/Crypto5.6.1/pch.h"
- #include "./../../../common/Crypto5.6.1/files.h"
- #include "./../../../common/Crypto5.6.1/default.h"
- #include "./../../../common/Crypto5.6.1/base64.h"
- #include "./../../../common/Crypto5.6.1/osrng.h"
-
- //AES
- #include "./../../../common/Crypto5.6.1/hex.h"
- using CryptoPP::HexEncoder;
- using CryptoPP::HexDecoder;
-
- #include "./../../../common/Crypto5.6.1/cryptlib.h"
- using CryptoPP::BufferedTransformation;
- using CryptoPP::AuthenticatedSymmetricCipher;
-
- #include "./../../../common/Crypto5.6.1/filters.h"
- using CryptoPP::StringSink;
- using CryptoPP::StringSource;
- using CryptoPP::AuthenticatedEncryptionFilter;
- using CryptoPP::AuthenticatedDecryptionFilter;
-
- #include "./../../../common/Crypto5.6.1/aes.h"
- using CryptoPP::AES;
-
- #include "./../../../common/Crypto5.6.1/gcm.h"
- using CryptoPP::GCM;
- using CryptoPP::GCM_TablesOption;
-
- #include <iostream>
- #include <string>
-
- USING_NAMESPACE(CryptoPP)
- USING_NAMESPACE(std)
-
- static inline RandomNumberGenerator& PSRNG(void);
- static inline RandomNumberGenerator& PSRNG(void)
- {
- static AutoSeededRandomPool rng;
- rng.Reseed();
- return rng;
- }
-
- bool encrypt_aes256_gcm(const char *aesKey, const char *aesIV,
- const char *inPlainText, char **outEncryptedBase64,
- int &dataLength);
- bool decrypt_aes256_gcm(const char *aesKey, const char *aesIV,
- const char *inBase64Text, char **outDecrypted, int &dataLength);
- void Base64Decode(const std::string &inString, std::string &outString);
- void HexDecode(const std::string &inString, std::string &outString);
-
- static std::string m_ErrorMessage;
-
- int main()
- {
- //using above code these key and iv was generated
- std::string hexKey =
- "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
- std::string hexDecodedKey;
- HexDecode(hexKey, hexDecodedKey);
-
- std::string hexIV = "E1E592E87225847C11D948684F3B070D";
- std::string hexDecodedIv;
- HexDecode(hexIV, hexDecodedIv);
-
- std::string plainText = "Test encryption and decryption";
- std::string encryptedWithJava =
- "A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==";
-
- printf("%s%s\n", "Plain Text: " , plainText.c_str());
-
- //encrypt - result base64 encoded string
- char *outEncryptedText=NULL;
- int outDataLength=0;
- bool bR = encrypt_aes256_gcm(hexDecodedKey.c_str(),
- hexDecodedIv.c_str(), plainText.c_str(),
- &outEncryptedText, outDataLength);
- printf("%s%s\n", "Encrypted base64 encoded: " , outEncryptedText);
-
- //decrypt - result plain string
- char* outDecryptedText=NULL;
- int outDecryptedDataLength=0;
- bR = decrypt_aes256_gcm(hexDecodedKey.c_str(),
- hexDecodedIv.c_str(), encryptedWithJava.c_str(),
- &outDecryptedText, outDecryptedDataLength);
- printf("%s%s\n", "Decrypted Text Encrypted by Java: " , outDecryptedText);
-
- if (plainText == outDecryptedText)
- {
- printf("%s\n", "Test Passed");
- }
- else
- {
- printf("%s\n", "Test Failed");
- }
-
- return 0;
- }
-
- bool encrypt_aes256_gcm(const char *aesKey, const char *aesIV,
- const char *inPlainText,
- char **outEncryptedBase64, int &dataLength)
- {
- bool bR = false;
- //const int TAG_SIZE = 12;
- std::string outText;
- std::string outBase64;
-
- if (strlen(aesKey)>31 && strlen(aesIV)>15)
- {
- try
- {
- GCM< AES >::Encryption aesEncryption;
- aesEncryption.SetKeyWithIV(reinterpret_cast<const byte*>(aesKey),
- AES::MAX_KEYLENGTH, reinterpret_cast<const byte*>(aesIV), AES::BLOCKSIZE);
- StringSource(inPlainText, true, new AuthenticatedEncryptionFilter
- (aesEncryption, new StringSink(outText)
- ) // AuthenticatedEncryptionFilter
- ); // StringSource
-
- CryptoPP::Base64Encoder *base64Encoder = new CryptoPP::Base64Encoder
- (new StringSink(outBase64), false);
- base64Encoder->PutMessageEnd(reinterpret_cast<const char=""
- unsigned=""> (outText.data()), outText.length());
- delete base64Encoder;
-
- dataLength = outBase64.length();
- if (outBase64.length()>0)
- {
- if (*outEncryptedBase64) free(*outEncryptedBase64);
- *outEncryptedBase64 = (char*)malloc(dataLength + 1);
- memset(*outEncryptedBase64, '\0', dataLength + 1);
- memcpy(*outEncryptedBase64, outBase64.c_str(), dataLength);
-
- bR = true;
- }
- else
- {
- m_ErrorMessage.append("Encryption Failed");
- }
- }
- catch (CryptoPP::InvalidArgument& e)
- {
- m_ErrorMessage.append(e.what());
- }
- catch (CryptoPP::Exception& e)
- {
- m_ErrorMessage.append(e.what());
- }
- }
- else
- {
- m_ErrorMessage.append("AES Key or IV cannot be empty");
- }
-
- outText.clear();
- outBase64.clear();
-
- return bR;
- }
-
- bool decrypt_aes256_gcm(const char *aesKey, const char *aesIV,
- const char *inBase64Text, char **outDecrypted, int &dataLength)
- {
- bool bR = false;
- std::string outText;
- std::string pszDecodedText;
- Base64Decode(inBase64Text, pszDecodedText);
-
- if (strlen(aesKey)>31 && strlen(aesIV)>15)
- {
- try
- {
- GCM< AES >::Decryption aesDecryption;
- aesDecryption.SetKeyWithIV(reinterpret_cast<const byte*>(aesKey),
- AES::MAX_KEYLENGTH,
- reinterpret_cast<const byte*>(aesIV), AES::BLOCKSIZE);
- AuthenticatedDecryptionFilter df(aesDecryption, new StringSink(outText));
-
- StringSource(pszDecodedText, true,
- new Redirector(df /*, PASS_EVERYTHING */)
- ); // StringSource
-
- bR = df.GetLastResult();
-
- dataLength = outText.length();
- if (outText.length()>0)
- {
- if (*outDecrypted) free(*outDecrypted);
- *outDecrypted = (char*)malloc(dataLength + 1);
- memset(*outDecrypted, '\0', dataLength + 1);
- memcpy(*outDecrypted, outText.c_str(), dataLength);
-
- bR = true;
- }
- else
- {
- m_ErrorMessage.append("Decryption Failed");
- }
- }
- catch (CryptoPP::HashVerificationFilter::HashVerificationFailed& e)
- {
- m_ErrorMessage.append(e.what());
- }
- catch (CryptoPP::InvalidArgument& e)
- {
- m_ErrorMessage.append(e.what());
- }
- catch (CryptoPP::Exception& e)
- {
- m_ErrorMessage.append(e.what());
- }
- }
- else
- {
- m_ErrorMessage.append("AES Key or IV cannot be empty");
- }
-
- return bR;
- }
-
- void Base64Decode(const std::string &inString, std::string &outString)
- {
- StringSource(inString, true, new Base64Decoder(new StringSink(outString)));
- }
-
- void HexDecode(const std::string &inString, std::string &outString)
- {
- StringSource(inString, true, new HexDecoder(new StringSink(outString)));
- }
此存储库包含此处的2个Apache Netbeans项目。请克隆存储库并在 Netbeans IDE中打开项目。您必须已配置Netbeans IDE才能编辑C++项目。
要构建,请在终端中打开 cryptopp870 文件夹并输入 make 命令。它将构建 libcryptopp.a 静态库。该库默认为OS体系结构。GcmAes(GcmAes)Netbeans 项目依赖于 libcryptopp.a 并链接到它。
库可用后,可以从 Netbeans IDE 单独构建这两个项目。GcmAesTest项目具有libGcmAes.so依赖,并且将预先构建。构建后,也可以调试项目。
测试程序验证少量加密和解密测试。其中之一是解密使用Java代码加密的文本(链接如下)。
它生成以下示例测试结果:
- Key=D303E8441BE72DD1501319D64A46CA6442031A29706000D2D3988175D7B492C4
- Len=64
-
- IV=D4AF4DB97D31492CA227D7BBB59AC494
- Len=32
- Key and IV Test OK
-
- Test 1 -> Encrypted base64 encoded:
- G3Elmv9n3cRyvVl5gZHtne9AEQHM3agHU1KTMvFxhSdWyASx5fD9uVfhVk+KRA==
- Test 1 -> Decrypted: Test encryption and decryption
- Test 1 -> Encryption / Decryption OK
-
- Plain Text: Test encryption and decryption
- Test 2 -> Encrypted base64 encoded:
- A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
- Test 2 -> Decrypted: Test encryption and decryption
- Test 2 -> Encryption / Decryption OK
-
- Test 3 -> Decrypted: Test encryption and decryption
- Test 3 -> Java Encrypted / C++ Decryption OK
-
- Test 4 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
- Test 4 -> Hex Encoded:
- 73796C6C61626963206B616E6120E28093206869726167616E612028E5B9B3E4BBAEE5908D2920616E64206B6174616B616E612028E78987E4BBAEE5908D29
- Test 4 -> Hex Encoding OK
-
- Test 5 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
- Test 5 -> Hex Decoded: syllabic kana – hiragana (平仮名) and katakana (片仮名)
- Test 5 -> Hex Decoding OK
-
- Test 6 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
- Test 6 -> Base64 Encoded:
- c3lsbGFiaWMga2FuYSDigJMgaGlyYWdhbmEgKOW5s+S7ruWQjSkgYW5kIGthdGFrYW5hICjniYfku67lkI0p
- Test 6 -> Base64 Encoding OK
-
- Test 7 -> Multi-byte Text: syllabic kana – hiragana (平仮名) and katakana (片仮名)
- Test 7 -> Base64 Decoded: syllabic kana – hiragana (平仮名) and katakana (片仮名)
- Test 7 -> Base64 Decoding OK
该测试项目还演示了如何将 libGcmAes.so 与Linux等系统上的其他C++项目一起使用。通常,只需将 GcmAes.h 包含在您的项目中,并且必须将您的项目与 libGcmAes.so 链接。代码使用 C++ 14 标准。
- /*
- Copyright (©) 2023 Kashif Mushtaq
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
-
- #ifndef __CRYPTOGRAPHER_INCLUDE_HEADER__
- #define __CRYPTOGRAPHER_INCLUDE_HEADER__
-
- #pragma once
- #include <iostream>
- #include <string>
- #include <stdio.h>
- #include <stdlib.h>
- #include <iostream>
- #include <fstream>
- #include <cstdlib>
- #include <syslog.h>
- #include <stdarg.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <signal.h>
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
-
- /**
- Exported for dynamic loading and calling
- */
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /*
- * Note:
- * All functions returning buffers like **out<name>
- * are allocated using new and are null terminated.
- * Users must clear them using delete *out<name>
- */
-
- // ------------------------------ libGcmAes.so Exports ---------------------------
- bool _base64Encode(/*[in]*/ const char *inPlainText,
- /*[out]*/ char **outBase64Encoded, /*[in, out]*/ int &dataLength);
- bool _base64Decode(/*[in]*/ const char *inBase64Text,
- /*[out]*/ char **outPlainText, /*[in, out]*/ int &dataLength);
- bool _hexDecode(/*[in]*/ const char *inHexEncodedText,
- /*[out]*/ char **outHexDecoded);
- bool _hexEncode(/*[in]*/ const char *inData, /*[out]*/ char **outHexEncoded);
-
- bool _encrypt_GcmAes256(/*[in]*/const char *inHexKey,
- /*[in]*/const char *inHexIv, /*[in]*/const char *inPlainText,
- /*[out]*/ char **outEncryptedBase64, /*[in, out]*/int &dataLength);
- bool _decrypt_GcmAes256(/*[in]*/const char *inHexKey,
- /*[in]*/const char *inHexIv, /*[in]*/const char *inBase64Text,
- /*[out]*/ char **outDecrypted, /*[in, out]*/int &dataLength);
-
- bool _getNewAESKeyAndIv(/*[out]*/ char **outHexKey,
- /*[out]*/ char **outHexIv, /*[in, out]*/int &outKeyLength,
- /*[in, out]*/ int &outIvLength);
- // ------------------------------ libGcmAes.so Exports ---------------------------
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif
- /*
- Copyright (©) 2023 Kashif Mushtaq
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
-
- /*
- * File: main.cpp
- * Author: kmushtaq
- *
- * Created on April 11, 2023, 9:21 AM
- */
-
- //Include GcmAES header and link this project against libGcmAes.so
- #include "GcmAes.h"
-
- #include <cstdlib>
- #include <regex>
- #include <cstring>
-
- using namespace std;
-
- /*
- *
- */
- int main(int argc, char** argv)
- {
- // lets first generate encryption Key and IV for AES 256 GCM.
- // Key size is 32 bytes and IV size is 16 bytes
- // Lib generated Key and IV are hex encoded.
- // Encryption and decryption function expects hex encoded Key and IV.
-
- std::string inHexKey;
- std::string inHexIV;
- char* pszKey = nullptr;
- char* pszIv = nullptr;
- int keyLen = 0;
- int ivLen = 0;
-
- std::string plainText = "Test encryption and decryption";
- bool result = false;
-
- /* ----------------------- Key Generation Test ----------------------- */
- result = _getNewAESKeyAndIv(&pszKey, &pszIv, keyLen, ivLen);
-
- if (result)
- {
- printf("Key=%s\nLen=%i\n\nIV=%s\nLen=%i\n", pszKey, keyLen, pszIv, ivLen);
- printf("Key and IV Test OK\n\n");
- }
- else
- {
- printf("%s", "Key and IV generation failed. Please check syslog for errors");
- return 1;
- }
- /* ----------------------- Key Generation Test ----------------------- */
-
- /* ----------------------- Encryption Decryption Test ----------------------- */
- //Save key and IV to call encryption and decryption functions
- inHexKey = pszKey;
- inHexIV = pszIv;
-
- char* outTestEncrypted = nullptr;
- int outTestEncryptedLen = 0;
-
- //encrypt - result base64 encoded
- result = _encrypt_GcmAes256(inHexKey.c_str(), inHexIV.c_str(),
- plainText.c_str(), &outTestEncrypted, outTestEncryptedLen);
- if (result)
- {
- printf("Test 1 -> Encrypted base64 encoded: %s\n", outTestEncrypted);
- }
- else
- {
- printf("%s", "Test 1 -> Encryption failed. Please check syslog for errors");
- return 1;
- }
-
- char* outTestDecrypted = nullptr;
- int outTestDecryptedLen = 0;
-
- //decrypt - result plain text
- result = _decrypt_GcmAes256(inHexKey.c_str(), inHexIV.c_str(),
- outTestEncrypted, &outTestDecrypted, outTestDecryptedLen);
- if (result && strcmp(plainText.c_str(), outTestDecrypted) == 0)
- {
- printf("Test 1 -> Decrypted: %s\n", outTestDecrypted);
- printf("Test 1 -> Encryption / Decryption OK\n\n");
- }
- else
- {
- printf("%s", "Test 1 -> Decryption failed. Please check syslog for errors");
- return 1;
- }
-
- inHexKey.clear();
- inHexIV.clear();
-
- //clear buffers
- if (outTestEncrypted) delete outTestEncrypted;
- outTestEncrypted = nullptr;
-
- if (outTestDecrypted) delete outTestDecrypted;
- outTestDecrypted = nullptr;
-
-
- //clear buffers allocated by _getNewAESKeyAndIv function
- if (pszKey) delete pszKey;
- pszKey = nullptr;
-
- if (pszIv) delete pszIv;
- pszIv = nullptr;
-
- /* ------------------ Encryption Decryption Test ----------------------- */
-
- /* ------------------ C++ Encryption and C++ Decryption Test ------------------ */
- std::string hexKey =
- "2192B39425BBD08B6E8E61C5D1F1BC9F428FC569FBC6F78C0BC48FCCDB0F42AE";
- std::string hexIV = "E1E592E87225847C11D948684F3B070D";
-
- printf("Plain Text: %s\n", plainText.c_str());
-
- char* outEncrypted = nullptr;
- int outEncryptedLen = 0;
-
- //encrypt - result base64 encoded
- result = _encrypt_GcmAes256(hexKey.c_str(), hexIV.c_str(),
- plainText.c_str(), &outEncrypted, outEncryptedLen);
- if (result)
- {
- printf("Test 2 -> Encrypted base64 encoded: %s\n", outEncrypted);
- }
- else
- {
- printf("%s", "Test 2 -> Encryption failed. Please check syslog for errors");
- return 1;
- }
-
- char* outDecrypted = nullptr;
- int outDecryptedLen = 0;
-
- //decrypt - result plain text
- result = _decrypt_GcmAes256(hexKey.c_str(),
- hexIV.c_str(), outEncrypted, &outDecrypted, outDecryptedLen);
- if (result && strcmp(plainText.c_str(), outDecrypted) == 0)
- {
- printf("Test 2 -> Decrypted: %s\n", outDecrypted);
- printf("Test 2 -> Encryption / Decryption OK\n\n");
- }
- else
- {
- printf("%s", "Test 2 -> Decryption failed. Please check syslog for errors");
- return 1;
- }
-
- //clear buffers
- if (outEncrypted) delete outEncrypted;
- outEncrypted = nullptr;
-
- if (outDecrypted) delete outDecrypted;
- outDecrypted = nullptr;
-
- /* ------------------ C++ Encryption and C++ Decryption Test ------------------ */
-
- /* ------------------ Java based Encryption and C++ Decryption Test ----------- */
- //Java Encrypted with same Key and IV as above
- // A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
-
- std::string javaEncrypted =
- "A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==";
- char* outCDecrypted;
- int outCDecryptedLen = 0;
-
- //decrypt - result plain text
- result = _decrypt_GcmAes256(hexKey.c_str(), hexIV.c_str(),
- javaEncrypted.c_str(), &outCDecrypted, outCDecryptedLen);
- if (result && strcmp(plainText.c_str(), outCDecrypted) == 0)
- {
- printf("Test 3 -> Decrypted: %s\n", outCDecrypted);
- printf("Test 3 -> Java Encrypted / C++ Decryption OK\n\n");
- }
- else
- {
- printf("%s", "Test 3 -> Java Decryption failed.
- Please check syslog for errors");
- return 1;
- }
-
- //clear buffers
- if (outCDecrypted) delete outCDecrypted;
- outCDecrypted = nullptr;
-
- /* ---------------- Java based Encryption and C++ Decryption Test --------------- */
-
- /*
- Result:
-
- Key=BF2F0CEC3D78EEB8388D8A78402510B9F3A99F7F69E98C6DB7168D0C57270EF4
- Len=64
- IV=FE6A26A45DB769F02C55CF12252F8A32
- Len=32
- Key and IV Test OK
- Test 1 -> Encrypted base64 encoded:
- 5NKdId7ZkBMWTtM5OhtPiaq1x0lBhbUSCxpcWK8PjjIGUvVdMdYET0Gw1mwmOw==
- Test 1 -> Decrypted: Test encryption and decryption
- Test 1 -> Encryption / Decryption OK
- Plain Text: Test encryption and decryptionTest 2 ->
- Encrypted base64 encoded: A/boAixWJKflKviHp2cfDl6l/xn1qw2MsHcKFkrOfm2XOVmawIFct4fS1w7wKw==
- Test 2 -> Decrypted: Test encryption and decryption
- Test 2 -> Encryption / Decryption OK
- Test 3 -> Decrypted: Test encryption and decryption
- Test 3 -> Java Encrypted / C++ Decryption OK
- RUN FINISHED; exit value 0; real time: 20ms; user: 0ms; system: 0ms
- */
-
- /* ----------------------- Hex Encoding / Decoding Test ----------------------- */
-
- std::string pszPlainText = "syllabic kana – hiragana (平仮名) and katakana (片仮名)";
- char* hexEncoded = nullptr;
- char* hexDecoded = nullptr;
-
- result = _hexEncode(pszPlainText.c_str(), &hexEncoded);
-
- if(result)
- {
- printf("Test 4 -> Multi-byte Text: %s\n", pszPlainText.c_str());
- printf("Test 4 -> Hex Encoded: %s\n", hexEncoded);
- printf("Test 4 -> Hex Encoding OK\n\n");
- }
- else
- {
- printf("%s", "Test 4 -> Encoding failed.");
- return 1;
- }
-
- result = _hexDecode(hexEncoded, &hexDecoded);
-
- if(result && strcmp(pszPlainText.c_str(), hexDecoded) == 0)
- {
- printf("Test 5 -> Multi-byte Text: %s\n", pszPlainText.c_str());
- printf("Test 5 -> Hex Decoded: %s\n", hexDecoded);
- printf("Test 5 -> Hex Decoding OK\n\n");
- }
- else
- {
- printf("%s", "Test 4 -> Decoding failed.");
- return 1;
- }
-
- if(hexEncoded) delete hexEncoded;
- if(hexDecoded) delete hexDecoded;
- hexEncoded = nullptr;
- hexDecoded = nullptr;
-
- /* ----------------------- Hex Encoding / Decoding Test ----------------------- */
-
-
- /* ----------------------- Base64 Encoding / Decoding Test -------------------- */
-
- char* base64Encoded = nullptr;
- char* base64Decoded = nullptr;
- int base64Len = pszPlainText.length();
-
- result = _base64Encode(pszPlainText.c_str(), &base64Encoded, base64Len);
-
- if(result)
- {
- printf("Test 6 -> Multi-byte Text: %s\n", pszPlainText.c_str());
- printf("Test 6 -> Base64 Encoded: %s\n", base64Encoded);
- printf("Test 6 -> Base64 Encoding OK\n\n");
- }
- else
- {
- printf("%s", "Test 6 -> Encoding failed.");
- return 1;
- }
-
- base64Len = strlen(base64Encoded);
- result = _base64Decode(base64Encoded, &base64Decoded, base64Len);
-
- if(result && strcmp(pszPlainText.c_str(), base64Decoded) == 0)
- {
- printf("Test 7 -> Multi-byte Text: %s\n", pszPlainText.c_str());
- printf("Test 7 -> Base64 Decoded: %s\n", base64Decoded);
- printf("Test 7 -> Base64 Decoding OK\n\n");
- }
- else
- {
- printf("%s", "Test 7 -> Decoding failed.");
- return 1;
- }
-
- if(base64Encoded) delete base64Encoded;
- if(base64Decoded) delete base64Decoded;
- base64Encoded = nullptr;
- base64Decoded = nullptr;
-
- /* ----------------------- Base64 Encoding / Decoding Test -------------------- */
-
- hexKey.clear();
- hexIV.clear();
- pszPlainText.clear();
-
- return 0;
- }
项目完全涵盖了上述Linux lib项目的所有功能、测试和用例。
请访问 GitHub上的Windows C++ x64 DLL和示例测试程序。
两个项目提供包装类和测试项目,用于调用 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。