c# - 将 advapi32.dll 加密功能移植到 Linux 容器 C#
问题描述
我们有使用 PublicKey 加密的遗留功能。我们希望将此代码路径迁移到 Linux 容器中。
advapi32.dll
在 Linux 中无效。我们需要使用在 Linux 容器中工作的相应 .net 核心跨平台代码。
CryptAcquireContext,CryptExportKey,CryptExportKey,CryptImportKey,CryptEncrypt,CryptGenKey,CryptDestroyKey,CryptReleaseContext
在 Linux 容器上支持的 C# ( ) 中编写相应 DllImport 方法的任何指针或指导?
这是我们的代码。
internal static string Encrypt(string textToEncrypt, string publicKey)
{
publicKey = publicKey.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ?
publicKey.Remove(0, 2) : publicKey;
// delete version string
string publicKeyMaterial = publicKey.Remove(0, 44);
byte[] publicKeyBytes = HexToByteArray(publicKeyMaterial);
IntPtr hProv = IntPtr.Zero;
if (CryptAcquireContext(ref hProv, IntPtr.Zero, null, PROV_RSA_AES, CRYPT_VERIFYCONTEXT) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error aquiring key container context. ErrorId: {0}",
Marshal.GetLastWin32Error()));
}
IntPtr hPublicKey = IntPtr.Zero;
// import public key to key container
if (CryptImportKey(hProv, publicKeyBytes, publicKeyBytes.Length, IntPtr.Zero, CRYPT_EXPORTABLE,
ref hPublicKey) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error importing key. ErrorId: {0}",
Marshal.GetLastWin32Error()));
}
IntPtr hSessionHandle = IntPtr.Zero;
if (CryptGenKey(hProv, new IntPtr(CALG_AES_192), CRYPT_EXPORTABLE,
ref hSessionHandle) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error generating session key. ErrorId: {0}",
Marshal.GetLastWin32Error()));
}
int sessionBlobLength = 0;
// exports length of wrapped session key
if (CryptExportKey(hSessionHandle, hPublicKey, SIMPLEBLOB, 0, IntPtr.Zero,
ref sessionBlobLength) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error exporting session key length. ErrorId: {0}, key: {1}, hSessionHandle: {2}, hPublicKey: {3}",
Marshal.GetLastWin32Error(), publicKey, hSessionHandle, hPublicKey));
}
byte[] exportedSessionKey = new byte[sessionBlobLength];
// exports session key wrapped with public key
if (CryptExportKey(hSessionHandle, hPublicKey, SIMPLEBLOB, 0, exportedSessionKey,
ref sessionBlobLength) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error exporting session key. ErrorId: {0}",
Marshal.GetLastWin32Error()));
}
byte[] bytesToEncrypt = Encoding.Unicode.GetBytes(textToEncrypt);
int dataLength = bytesToEncrypt.Length;
int bufferLen = bytesToEncrypt.Length;
// get the length of the cipher text
if (CryptEncrypt(hSessionHandle, 0, true, 0, null, ref dataLength, bufferLen) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error while getting cipher text length. ErrorId: {0}",
Marshal.GetLastWin32Error()));
}
byte[] buffer = new byte[dataLength];
Buffer.BlockCopy(bytesToEncrypt, 0, buffer, 0, bytesToEncrypt.Length);
dataLength = bytesToEncrypt.Length;
bufferLen = buffer.Length;
if (CryptEncrypt(hSessionHandle, 0, true, 0, buffer, ref dataLength, bufferLen) == 0)
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Error while encrypting data. ErrorId: {0}",
Marshal.GetLastWin32Error()));
}
// key/container clean up
CryptDestroyKey(hSessionHandle);
CryptDestroyKey(hPublicKey);
CryptReleaseContext(hProv, 0);
EncryptedData encryptedData = new EncryptedData();
encryptedData.CipherText = buffer;
encryptedData.ExportedSessionKey = exportedSessionKey;
encryptedData.PublicKeyHeader = EncryptedData.ExtractPublicKeyHeader(publicKey);
encryptedData.SessionKeyType = KeyType.SESSION_KEY_AES_192;
return encryptedData.ToString();
}
private static byte[] HexToByteArray(String hexString)
{
int OutputByteCount = hexString.Length / 2;
byte[] bytes = new byte[OutputByteCount];
for (int i = 0; i < hexString.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
return bytes;
}
#region CryptoAPI Constants
private const int CRYPT_VERIFYCONTEXT = -268435456;
private const int PROV_RSA_FULL = 1;
private const int PROV_RSA_AES = 24;
private const int CRYPT_EXPORTABLE = 1;
private const int SIMPLEBLOB = 1;
private const int CALG_3DES = 26115; // (3 << 13) | (3 << 9) | 3;
private const int CALG_AES_192 = 26126; // (3 << 13) | (3 << 9) | 14;
#endregion CryptoAPI Constants
[DllImport(@"advapi32.dll", SetLastError = true)] // do not remove SetLastError
private static extern int CryptAcquireContext(ref IntPtr phProv, IntPtr pszContainer,
string pszProvider, int dwProvType, int dwFlags);
[DllImport(@"advapi32.dll", SetLastError = true)]
private static extern int CryptExportKey(IntPtr hKey, IntPtr hExpKey, int dwBlobType,
int dwFlags, IntPtr pbData, ref int pdwDataLen);
[DllImport(@"advapi32.dll", SetLastError = true)]
private static extern int CryptExportKey(IntPtr hKey, IntPtr hExpKey, int dwBlobType,
int dwFlags, byte[] pbData, ref int pdwDataLen);
[DllImport(@"advapi32.dll", SetLastError = true)]
private static extern int CryptImportKey(IntPtr hProv, byte[] pbData, int dwDataLen,
IntPtr hPubKey, int dwFlags, ref IntPtr phKey);
[DllImport(@"advapi32.dll")]
private static extern int CryptEncrypt(IntPtr hKey, int hHash, bool Final, int dwFlags,
byte[] pbData, ref int pdwDataLen, int dwBufLen);
[DllImport(@"advapi32.dll", SetLastError = true)]
private static extern int CryptGenKey(IntPtr hProv, IntPtr Algid, int dwFlags,
ref IntPtr phKey);
[DllImport(@"advapi32.dll", SetLastError = true)]
private static extern int CryptDestroyKey(IntPtr hKey);
[DllImport(@"advapi32.dll", SetLastError = true)]
private static extern int CryptReleaseContext(IntPtr hProv, int dwFlags);
private enum KeyType : short
{
SESSION_KEY_3DES = 1,
SESSION_KEY_AES_192 = 2
}
private struct EncryptedData { ... }
解决方案
推荐阅读
- java - 没有注册的 Eureka 客户端实例。(JAVA11,Maven)
- java - Drools:如何在非表达式中实现和( && )条件?
- python - 在 py-rewrite 中创建城市字典命令?
- android - 如何在 JNI NDK Android 中正确简单地使用回调
- firebase - 我们可以将 Sentry 与 NoGMS 一起使用吗
- java - 从 API 下载 JSON 文件并将其转换为文本
- jmeter - 需要根据jmeter中的条件提取所有数据
- amazon-web-services - 在 Beanstalk 的 ALB 上将 http 重定向到 https,而不支持实例上的 https
- salesforce - 在内部和外部更新 Salesforce 中的自定义字段
- ios - UICollectionView 单元格创建绕过了`willDisplay cell:` 调用?