gpt4 book ai didi

C#:解码 OAEP 填充奇怪问题时出错

转载 作者:太空狗 更新时间:2023-10-29 23:49:31 30 4
gpt4 key购买 nike

我目前正在研究一个类,该类使用 RSACryptoServiceProvider 执行主 key 加密和解密操作,使用智能卡的 X509 证书加密随机生成的加密 key 来加密大量文本。但是,当我将 fOEAP 填充选项设置为 true 时,每次解密时都会出现“解码 OAEP 填充时出错”错误。我检查了 key 大小,它在可接受的范围内。我通过断点确保从加密函数返回的 Base64 字符串与再次加载文件时传递回解密函数的加密 Base64 字符串完全相同。

key 对肯定是正确的,因为它在没有 OAEP 的情况下也能正常工作。我也检查了文本编码。

编辑:事实证明这可能是智能卡特定问题,当我尝试使用本地 X509 证书解密时解密成功。

编辑:这是失败的解密代码:

string TestString = "Hello World!";
X509Certificate2 cert = DRXEncrypter.GetCertificate("Select a test certificate", "Select a certificate to use for this test from the local store.");
string key = DRXEncrypter.GenerateEncryptionKey(214);
Console.WriteLine("Encryption Key: " + key);

string encrypted = DRXEncrypter.EncryptBody(TestString, key);
Console.WriteLine("Encrypted Body: " + encrypted);

string cryptokey = DRXEncrypter.EncryptWithCert(cert, key);
Console.WriteLine("Encrypted Decryption Key: " + cryptokey);

string decrypted = DRXEncrypter.DecryptBody(encrypted, cryptokey, cert);
Console.WriteLine("Decrypted Body: " + decrypted);

Console.WriteLine("Output String: " + decrypted + ".");

这是我编写的加密提供程序类的代码。我已经在这个问题上停留了几个小时,所以如果有人能帮助我,那就太好了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;

namespace CoreDRXEditor
{
public class DRXEncrypter
{
private byte[] Salt = Encoding.ASCII.GetBytes("81PO9j8I1a94j");
private string EncryptionKey;
private const bool UseOAEP = true;

public DRXEncrypter(string EncryptionKey)
{
this.EncryptionKey = EncryptionKey;
}

public static string EncryptBody(string body, string encryptionkey)
{
// Use the plaintext master key to encrypt the body.
DRXEncrypter enc = new DRXEncrypter(encryptionkey);

// Encrypt the body.
return enc.Encrypt(body);
}

public static int GetMaxKeySize(X509Certificate2 cert)
{
RSACryptoServiceProvider csp = cert.PublicKey.Key as RSACryptoServiceProvider;

return csp.KeySize;
}

public static string DecryptBody(string body, string encryptionkey, X509Certificate2 cert)
{
// Decrypt the encrypted encryption key with the certificate.
string DecryptedKey = Convert.ToBase64String(DecryptWithCert(cert, encryptionkey));

// Create a new DRXEncrypter using the decrypted encryption key to decrypt the body.
DRXEncrypter enc = new DRXEncrypter(DecryptedKey);

// Return the decrypted body.
return enc.Decrypt(body);
}

public static string GenerateEncryptionKey(int KeyLength)
{
using (RandomNumberGenerator rng = new RNGCryptoServiceProvider())
{
byte[] CryptoBytes = new byte[KeyLength];
rng.GetBytes(CryptoBytes);

return Convert.ToBase64String(CryptoBytes);
}
}

public static X509Certificate2 GetCertificate(string title, string message)
{
X509Store cstore = new X509Store(StoreLocation.CurrentUser);
cstore.Open(OpenFlags.ReadOnly);

X509CertificateCollection certs = X509Certificate2UI.SelectFromCollection(cstore.Certificates, title, message, X509SelectionFlag.SingleSelection);

if (certs.Count == 1)
{
X509Certificate2 mcert = certs[0] as X509Certificate2;
return mcert;
}
else
{
return null;
}
}

public static string EncryptWithCert(X509Certificate2 cert, string PlainText)
{
RSACryptoServiceProvider csp = cert.PublicKey.Key as RSACryptoServiceProvider;

byte[] PlainBytes = Convert.FromBase64String(PlainText);

// This converts the plain text into a byte array and then encrypts the raw bytes.
byte[] CryptoBytes = csp.Encrypt(PlainBytes, UseOAEP);

// This converts the encrypted bytes into a Base64 string.
string ReturnString = Convert.ToBase64String(CryptoBytes);

return ReturnString;
}

public static byte[] DecryptWithCert(X509Certificate2 cert, string EncryptedText)
{
RSACryptoServiceProvider csp = cert.PrivateKey as RSACryptoServiceProvider;

//CspParameters csps = new CspParameters();

byte[] EncryptedBytes = Convert.FromBase64String(EncryptedText);

// This converts the encrypted, Base64 encoded byte array from EncryptWithCert() to a byte[] and decrypts it.
byte[] CryptoBytes = csp.Decrypt(EncryptedBytes, UseOAEP);

return CryptoBytes;
}

public string Encrypt(string PlainText)
{
RijndaelManaged Algorithm = null;
string Output = null;

try
{
Rfc2898DeriveBytes PrivateKey = new Rfc2898DeriveBytes(this.EncryptionKey, this.Salt);


Algorithm = new RijndaelManaged();
Algorithm.Key = PrivateKey.GetBytes(Algorithm.KeySize / 8);
Algorithm.Padding = PaddingMode.PKCS7;

ICryptoTransform Encryption = Algorithm.CreateEncryptor(Algorithm.Key, Algorithm.IV);

using (MemoryStream msa = new MemoryStream())
{
msa.Write(BitConverter.GetBytes(Algorithm.IV.Length), 0, sizeof(int));
msa.Write(Algorithm.IV, 0, Algorithm.IV.Length);
using (CryptoStream csa = new CryptoStream(msa, Encryption, CryptoStreamMode.Write))
{
using (StreamWriter swa = new StreamWriter(csa))
{
swa.Write(PlainText);
}
}
Output = Convert.ToBase64String(msa.ToArray());
}
}
finally
{
if (Algorithm != null)
{
Algorithm.Clear();
}
}

return Output;
}

public string Decrypt(string EncryptedText)
{
RijndaelManaged Algorithm = null;
string Output = null;

try
{
Rfc2898DeriveBytes PrivateKey = new Rfc2898DeriveBytes(this.EncryptionKey, this.Salt);

byte[] KeyBytes = Convert.FromBase64String(EncryptedText);
using (MemoryStream msb = new MemoryStream(KeyBytes))
{
Algorithm = new RijndaelManaged();
Algorithm.Key = PrivateKey.GetBytes(Algorithm.KeySize / 8);
Algorithm.IV = ReadByteArray(msb);
Algorithm.Padding = PaddingMode.PKCS7;
ICryptoTransform Decryption = Algorithm.CreateDecryptor(Algorithm.Key, Algorithm.IV);
using (CryptoStream csb = new CryptoStream(msb, Decryption, CryptoStreamMode.Read))
{
using (StreamReader srb = new StreamReader(csb))
{
Output = srb.ReadToEnd();
}
}

}
}
finally
{
if (Algorithm != null)
{
Algorithm.Clear();
}
}

return Output;
}

public static string Sha512(string ToHash)
{
using (SHA512 SHA = new SHA512Managed())
{
byte[] HashByte = Encoding.UTF8.GetBytes(ToHash);
byte[] HashBytes = SHA.ComputeHash(HashByte);
string Hash = System.Text.Encoding.UTF8.GetString(HashBytes, 0, HashBytes.Length);
return Hash;
}
}

public static string Base64Encode(string data)
{
byte[] str = Encoding.UTF8.GetBytes(data);
return Convert.ToBase64String(str);
}

public static string Base64Decode(string data)
{
byte[] str = Convert.FromBase64String(data);
return Encoding.UTF8.GetString(str);
}

private byte[] ReadByteArray(Stream st)
{
byte[] Length = new byte[sizeof(int)];
st.Read(Length, 0, Length.Length);
byte[] Buffer = new byte[BitConverter.ToInt32(Length, 0)];
st.Read(Buffer, 0, Buffer.Length);

return Buffer;
}
}
}

最佳答案

我今天一直在用智能卡(或者更准确地说,是启用了智能卡 PIV 小程序的 Yubikey Neo)争论这个问题;使用此代码:

var encryptor = (RSACryptoServiceProvider)c.PublicKey.Key;
var decryptor = (RSACryptoServiceProvider)c.PrivateKey;

var encrypt = encryptor.Encrypt(bytes, RSAEncryptionPadding.Pkcs1);
var decrypt = decryptor.Decrypt(encrypt, RSAEncryptionPadding.Pkcs1);

我发现我使用的填充算法很重要。如果我使用 PKCS1 填充,一切正常。如果我使用 OaepSHA1,我会收到 Error while decoding [...] 错误。如果我使用其他任何东西(例如,OaepSHA256),我会得到一个Not supported 错误。

我只能得出结论,我的智能卡不能正确支持 OAEP SHA1,但是用 PKCS#1 填充一切都很好。

即使这回答了您已知的问题,对于其他使用智能卡的人来说,它也可能作为另一个数据点很有用。

关于C#:解码 OAEP 填充奇怪问题时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44437196/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com