问题
From what I can tell, TLS 1.1 requires the contents of the CertificateVerify message to be a digitally signed value using the concatenation of two hash algorithms (MD5 and SHA1). Is this possible to do in .NET using the RSACryptoServiceProvider?
This does not work:
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(...);
rsa.SignData(data, new MD5SHA1());
}
This also does not work:
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(...);
rsa.SignHash(new MD5SHA1().ComputeHash(data), "MD5SHA1");
}
(MD5SHA1 is an implementation of HashAlgorithm.)
Presumably this does not work because the signature embeds the OID of the hash algorithm, and MD5-SHA1 does not have a valid OID. Is this possible in .NET? Am I misunderstanding TLS 1.1?
回答1:
In case it helps anyone else, I used the BigInteger class to make this work. What is called "signing" in TLS 1.1 is really just private-key encryption, which can be done using BigInteger math.
Sign
var hash = new MD5SHA1().ComputeHash(data);
var input = new BigInteger(hash);
return input.ModPow(new BigInteger(privateExponent),
new BigInteger(modulus)).GetBytes();
Verify
var hash = new MD5SHA1().ComputeHash(data);
var input = new BigInteger(signature);
var output = input.ModPow(new BigInteger(publicExponent),
new BigInteger(modulus)).GetBytes();
var rehash = SubArray(output, output.Length - 36);
return SequencesAreEqual(hash, rehash);
Note that you still have to add padding yourself to the output. (0x0001FFFFFF...FF00{data})
Signing can be optimized using CRT parameters (p, q, etc.), but that's a problem for another day.
来源:https://stackoverflow.com/questions/19407581/rsa-signing-using-md5-sha1-hash-algorithm