我很难复制oracle如何使用AES 256 + CBC + PKCS5 / 7将其复制到C#中。感谢您的帮助。
我在oracle包中有以下功能(简化):
--Character set used by GEN_ENCRYPT_PASSWORD and GEN_DECRYPT_PASSWORD
G_CHARACTER_SET VARCHAR2(10) := 'AL32UTF8';
FUNCTION GEN_ENCRYPT_PASSWORD(p_in_val IN VARCHAR2
,p_key IN VARCHAR2
,p_iv IN VARCHAR2 := NULL)
RETURN RAW
IS
l_enc_val RAW(4000);
l_enc_algo PLS_INTEGER;
l_in RAW(4000);
l_iv RAW(4000);
l_key RAW(4000);
--l_ret VARCHAR2(4000 CHAR);
v_mod NUMBER;
BEGIN
l_in := UTL_I18N.STRING_TO_RAW(data => p_in_val, dst_charset => G_CHARACTER_SET);
l_iv := UTL_I18N.STRING_TO_RAW(p_iv, G_CHARACTER_SET);
l_key := UTL_I18N.STRING_TO_RAW(data => p_key, dst_charset => G_CHARACTER_SET);
l_enc_algo := DBMS_CRYPTO.encrypt_aes256;
--chain_cbc: Cipher Block Chaining. Plaintext is XORed with the previous ciphertext block before it is encrypted.
--pad_pkcs5: Provides padding which complies with the PKCS #5: Password-Based Cryptography Standard.
v_mod := (l_enc_algo + DBMS_CRYPTO.chain_cbc + DBMS_CRYPTO.pad_pkcs5);
l_enc_val := DBMS_CRYPTO.encrypt(src => l_in, KEY => l_key, typ => v_mod);
--l_ret := RAWTOHEX(l_enc_val);
RETURN l_enc_val;
END GEN_ENCRYPT_PASSWORD;
FUNCTION GEN_DECRYPT_PASSWORD(p_in_val IN RAW
,p_key IN VARCHAR2
,p_iv IN VARCHAR2 := NULL)
RETURN VARCHAR2
IS
l_enc_val RAW(4000);
l_enc_algo PLS_INTEGER;
l_in RAW(4000);
l_iv RAW(4000);
l_key RAW(4000);
l_ret VARCHAR2(4000 CHAR);
v_mod NUMBER;
BEGIN
l_in := p_in_val; --UTL_I18N.STRING_TO_RAW(data => p_in_val, dst_charset => G_CHARACTER_SET);
l_iv := UTL_I18N.STRING_TO_RAW(p_iv, G_CHARACTER_SET);
l_key := UTL_I18N.STRING_TO_RAW(data => p_key, dst_charset => G_CHARACTER_SET);
l_enc_algo := DBMS_CRYPTO.encrypt_aes256;
--chain_cbc: Cipher Block Chaining. Plaintext is XORed with the previous ciphertext block before it is encrypted.
--pad_pkcs5: Provides padding which complies with the PKCS #5: Password-Based Cryptography Standard.
v_mod := (l_enc_algo + DBMS_CRYPTO.chain_cbc + DBMS_CRYPTO.pad_pkcs5);
l_enc_val := DBMS_CRYPTO.decrypt(src => l_in, KEY => l_key, typ => v_mod);
l_ret := UTL_I18N.raw_to_char(data => l_enc_val, src_charset => G_CHARACTER_SET);
RETURN l_ret;
END GEN_DECRYPT_PASSWORD;
然后我运行了查询:
SELECT pkg_Encyption_Test.GEN_ENCRYPT_PASSWORD('Test', '12345678901234567890123456789012', '26744a68b53dd87a') Encrypted FROM DUAL;
--Result: 7D2894678D46C769B3001BD75F603E3C
解密结果:
SELECT pkg_Encyption_Test.GEN_DECRYPT_PASSWORD('7D2894678D46C769B3001BD75F603E3C', '12345678901234567890123456789012', '26744a68b53dd87a') Decrypt from dual;
--Result: Test
所以上面都有效,问题是如何将C#转换为解密结果? 示例控制台应用程序:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace SSO_EncryptionTest
{
class Program
{
/* ORACLE
* TEXT ENC: 7D2894678D46C769B3001BD75F603E3C
* TEXT: Test
* KEY: 12345678901234567890123456789012
* .NET
* ENC: EAAAADI2NzQ0YTY4YjUzZGQ4N2GfHsbuE8t1/hhwz3v9isJ1
*/
static void Main(string[] args)
{
//Use the values from Oracle
string inputText = "Test";
string encryptedTextValue = "7D2894678D46C769B3001BD75F603E3C";
string encryptPrivateKey = "12345678901234567890123456789012";
string encryptSharedIV = "26744a68b53dd87a";
Console.WriteLine("******************** Initial values from Oracle ******************");
Console.WriteLine("inputText: '{0}'", inputText);
Console.WriteLine("encryptedTextValue: '{0}'", encryptedTextValue);
Console.WriteLine("encryptPrivateKey: '{0}'", encryptPrivateKey);
Console.WriteLine("encryptSharedIV: '{0}'", encryptSharedIV);
Console.WriteLine();
//This is just here to convert the Encrypted byte array to a string for viewing purposes.
UTF8Encoding UTF = new UTF8Encoding();
byte[] inputTextByte = UTF.GetBytes(inputText);
byte[] encryptedTextValueByte = UTF.GetBytes(encryptedTextValue);
byte[] encryptPrivateKeyByte = UTF.GetBytes(encryptPrivateKey);
byte[] encryptSharedIvByte = UTF.GetBytes(encryptSharedIV);
string Encrypted_Text;
//string Decrypted;
try
{
Console.WriteLine("********************Encryption Example******************");
Console.WriteLine("Plain text is: '{0}'", inputText);
Encrypted_Text = EncryptOracleAES(inputTextByte, encryptPrivateKeyByte, encryptSharedIvByte);
Console.WriteLine("Encrypted text is: '{0}'", Encrypted_Text);
Console.WriteLine();
/*Console.WriteLine("********************Decryption Example******************");
Console.WriteLine("Input Encrypted text is '{0}'", XXXXXXXXXXXX);
Decrypted = "";
Console.WriteLine("Decrypted text is: '{0}'", Decrypted);*/
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.Message);
}
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
public static string EncryptOracleAES(byte[] plainText, byte[] privateKey, byte[] sharedIVKey)
{
//select UTL_I18N.STRING_TO_RAW('Test', 'AL32UTF8') from dual;
//54657374
string outStr = null; // Encrypted string to return
AesManaged aesAlg = null;
try
{
aesAlg = new AesManaged();
aesAlg.Key = privateKey;
aesAlg.KeySize = 256;
aesAlg.BlockSize = 128;
aesAlg.Padding = PaddingMode.PKCS7; //Same as PKCS5/7
aesAlg.Mode = CipherMode.CBC;
aesAlg.IV = sharedIVKey;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, sharedIVKey);
using (MemoryStream msEncrypt = new MemoryStream())
{
// prepend the IV
msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
outStr = Convert.ToBase64String(msEncrypt.ToArray());
}
}
finally
{
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return outStr;
}
}
}
但我的结果不一致:
******************** Initial values from Oracle ******************
inputText: 'Test'
encryptedTextValue: '7D2894678D46C769B3001BD75F603E3C'
encryptPrivateKey: '12345678901234567890123456789012'
encryptSharedIV: '26744a68b53dd87a'
********************Encryption Example******************
Plain text is: 'Test'
Encrypted text is: 'EAAAADI2NzQ0YTY4YjUzZGQ4N2FCXNXYzo2xWZym3dNFwCSJ'
我错过了什么?
答案 0 :(得分:2)
主要问题实际上是我的选择语句在传递IV值(与解密相同)时错过了参数'AES256'...我告诉同事不断的烦恼:)。< / p>
SELECT pkg_Encyption_Test.GEN_ENCRYPT_PASSWORD('Test', '12345678901234567890123456789012', '26744a68b53dd87a') Encrypted FROM DUAL;
--Result: 7D2894678D46C769B3001BD75F603E3C
应该是:
SELECT pkg_Encyption_Test..GEN_ENCRYPT_PASSWORD('Test'
,'12345678901234567890123456789012'
,'AES256' --Or NULL
,'26744a68b53dd87a26744a68b53dd87a')
Encrypted
FROM DUAL;
--Result: E320A0CABF881088A424B4F36F188029
这需要重构,但总体思路就在那里。
课程:AesEncryption
public static AesCryptoServiceProvider AesEncryptionType(byte[] privateKeyByte, byte[] sharedIVKeyByte)
{
var aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = sharedIVKeyByte;
aes.Key = privateKeyByte;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
return aes;
}
变化我去了:
public static string EncryptUsingAes(byte[] inputTextByte, byte[] privateKeyByte, byte[] sharedIVKeyByte)
{
using (var aesEncryption = AesEncryption.AesEncryptionType(privateKeyByte, sharedIVKeyByte))
{
// Convert string to byte array
byte[] dest = new byte[inputTextByte.Length];
// encryption
using (ICryptoTransform encrypt = aesEncryption.CreateEncryptor(aesEncryption.Key, aesEncryption.IV))
{
dest = encrypt.TransformFinalBlock(inputTextByte, 0, inputTextByte.Length);
encrypt.Dispose();
}
return BitConverter.ToString(dest).Replace("-", "");
}
}
public static string DecryptUsingAes(byte[] inputTextByte, byte[] privateKeyByte, byte[] sharedIVKeyByte)
{
using (var aesDecryption = AesEncryption.AesEncryptionType(privateKeyByte, sharedIVKeyByte))
{
// Convert string to byte array
byte[] dest = new byte[inputTextByte.Length];
// encryption
using (ICryptoTransform decrypt = aesDecryption.CreateDecryptor(aesDecryption.Key, aesDecryption.IV))
{
dest = decrypt.TransformFinalBlock(inputTextByte, 0, inputTextByte.Length);
decrypt.Dispose();
}
// Convert byte array to UTF8 string
return Encoding.UTF8.GetString(dest); ;
}
}
主要:
private static void Main(string[] args)
{
//Use the values from Oracle
string inputText = "Test";
string encryptionType = "AES256";
string encryptPrivateKey = "12345678901234567890123456789012";
string encryptSharedIV = "26744a68b53dd87a";//26744a68b53dd87a26744a68b53dd87a";
string encryptedTextValue = "E320A0CABF881088A424B4F36F188029";
Console.WriteLine("******************** Initial values from Oracle ******************");
Console.WriteLine("inputText: '{0}'", inputText);
Console.WriteLine("encryptionType: '{0}'", encryptionType);
Console.WriteLine("encryptedTextValue: '{0}'", encryptedTextValue);
Console.WriteLine("encryptPrivateKey: '{0}'", encryptPrivateKey);
Console.WriteLine("encryptSharedIV: '{0}'", encryptSharedIV);
//OracleRaw
string oracleRawText = "54657374";
string oracleRawPrivateKey = "3132333435363738393031323334353637383930313233343536373839303132";
string oracleRawSharedIV = "32363734346136386235336464383761"; //26744a68b53dd87a - IV is 16 byte array.
Console.WriteLine("******************** Initial values from Oracle OracleRaw ******************");
Console.WriteLine("oracleRawText: '{0}'", oracleRawText);
Console.WriteLine("oracleRawPrivateKey: '{0}'", oracleRawPrivateKey);
Console.WriteLine("oracleRawSharedIV: '{0}'", oracleRawSharedIV);
Console.WriteLine();
//This is just here to convert the Encrypted byte array to a string for viewing purposes.
var utf = new UTF8Encoding();
byte[] inputTextByte = utf.GetBytes(inputText); //byte: 4 - "Test"
byte[] privateKeyByte = utf.GetBytes(encryptPrivateKey); //byte: 32 - "12345678901234567890123456789012"
byte[] sharedIVByte = utf.GetBytes(encryptSharedIV); //byte: 16 - "26744a68b53dd87a"
//string Decrypted;
try
{
string encryptedText = string.Empty;
byte[] oracleRawTextByte = StringToByteArray(oracleRawText);
byte[] oracleRawPrivateKeyByte = StringToByteArray(oracleRawPrivateKey);
byte[] oracleRawSharedIVByte = StringToByteArray(oracleRawSharedIV);
encryptedText = EncryptUsingAes(oracleRawTextByte, oracleRawPrivateKeyByte, oracleRawSharedIVByte);
Console.WriteLine("********************Encryption Example EncryptUsingAes(OracleRaw) ******************");
Console.WriteLine("Plain text is: '{0}'", inputText);
Console.WriteLine("Encrypted text is: '{0}'", encryptedText);
Console.WriteLine();
encryptedText = EncryptUsingAes(inputTextByte, privateKeyByte, sharedIVByte);
Console.WriteLine("********************Encryption Example EncryptUsingAes******************");
Console.WriteLine("Plain text is: '{0}'", inputText);
Console.WriteLine("Encrypted text is: '{0}'", encryptedText);
Console.WriteLine();
Console.WriteLine("********************Encryption Example DecryptUsingAes******************");
Console.WriteLine("Encrypted text is: '{0}'", encryptedText);
byte[] cypherText = StringToByteArray(encryptedText);
encryptedText = DecryptUsingAes(cypherText, privateKeyByte, sharedIVByte);
Console.WriteLine("Plain text is: '{0}'", encryptedText);
Console.WriteLine();
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.Message);
}
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
}