我试图弄清楚如何使用ANSI X9.31版本的RSA数字签名算法创建数字签名。这与PKCS#1实现不同,主要是由于填充方案。
我以为我可以使用RSACryptoServiceProvider来SignHash;但是,这使用PKCS#1或OAEP。我无法弄清楚如何使用ANS X9.31填充。帮助
编辑:如果我使用BouncyCastle,我是否需要使用" RSABlindingEngine"或者我可以只使用" RSAEngine"?见下面的例子:
using System.Security.Cryptography;
public byte[] SignSha256AnsiX931Rsa(
byte[] data,
System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
{
// Do a SHA-256 hash of the data, using CNG
SHA256Cng sha = new SHA256Cng();
byte[] digest = sha.ComputeHash(data);
// Pad the hash using ANSI X9.31 padding scheme
byte[] paddedHash = AnsiX931PadData(digest);
// Encrypt the data using RSA encryption
return RsaEncryptData(paddedHash, certificate);
}
/// <summary>
/// Pads the passed in SHA-256 hash (32-bytes) using the padding scheme
/// specified for ANS X9.31 RSA digital signatures.
/// </summary>
/// <param name="sha256HashedData">The 32-byte hash</param>
public byte[] AnsiX931PadData(byte[] sha256HashedData)
{
// N = Modulus Length (in bytes) = 256, where modulus is 2048-bits (length of private key)
// M = Message
// k = Hash Output = Digest = Hash(M)
// z = Len(k) (in bytes) = 32, where using Hash = SHA-256
// p = number of fixed padding bytes, in this case 4 (6b, ba, 34, and cc)
//
// Padded Hash = 6b [bb]*x ba [k] 34 cc, where x = 220 (N - z - 4 = 256 - 32 - 4 = 220)
// [6b bb bb ... bb ba] [Hash(M)] [hashID=34] [cc]
//
// See:
// http://www.drdobbs.com/rsa-digital-signatures/184404605?pgno=6
// http://books.google.com/books?id=7gBn_gEBQesC&lpg=PA388&dq=x9.31%20padding&pg=PA386#v=onepage&q=x9.31%20padding&f=false
const int MOD_LENGTH = 256; // 2048-bit private key length
const int PAD_LENGTH = 4; // number of fixed padding bytes, in this case 4 (6b, ba, 34, and cc)
const int HASH_LENGTH = 32; // where using Hash = SHA-256
if (sha256HashedData.Length != HASH_LENGTH) throw new ArgumentException("The hash provided is the incorrect length");
List<byte> paddedHash = new List<byte>(MOD_LENGTH);
paddedHash.Add(0x6b);
int bbRepeats = MOD_LENGTH - HASH_LENGTH - PAD_LENGTH;
for (int ii = 0; ii < bbRepeats; ii++)
{
paddedHash.Add(0xbb);
}
paddedHash.Add(0xba);
paddedHash.AddRange(sha256HashedData);
paddedHash.Add(0x34); // SHA-256 Hash ID; 0x33 = SHA-1
paddedHash.Add(0xcc);
return paddedHash.ToArray();
}
/// <summary>
/// Encrypts the data using an X509 certificate and the RSA encryption scheme
/// </summary>
public byte[] RsaEncryptData(
byte[] data,
System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
{
Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine engine = new Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine();
engine.Init(true, getBouncyPrivateKey(certificate));
return engine.ProcessBlock(data, 0, data.Length);
}
/// <summary>
/// Gets the private key from an X509Certificate
/// </summary>
private Org.BouncyCastle.Crypto.AsymmetricKeyParameter getBouncyPrivateKey(
System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
{
// Need to transform the key from X509 to RSACrypto so we can do SHA-256 since
// X509 only supports SHA-1:
System.Security.Cryptography.RSACryptoServiceProvider key = new System.Security.Cryptography.RSACryptoServiceProvider(2048);
// Round-trip the key to XML and back, there might be a better way but this works
key.FromXmlString(certificate.PrivateKey.ToXmlString(true));
return Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(key).Private;
}
答案 0 :(得分:0)
棘手。您可以使用或从Bouncy Castle for C#中提取RSA致盲引擎,然后自己执行填充/取消填充。它在this age old Dr Dobbs article中描述。