无法使二进制数据上的 RSA signature/verifiction 正常工作。任何工作示例?
Cannot get my RSA signature/verifiction on BINARY data to work. Any working examples?
我正在尝试对二进制数据使用 RSA 签名和验证,但它不起作用,无论如何 RSA.VerifyData 总是 returns false。
基本上我有一个二进制序列化的对象:
public class MyObject {
public OtherClass Property1 { get; set; }
public Trailer Trailer { get; set; }
}
public class Trailer {
public byte[] Hash {get;set; } // Any hash
public byte[] Signature {get;set; }
}
基本上对象有自己的属性集,这里只有一个 (Property1)。然后我计算没有预告片的对象的哈希值并将其放在 Trailer.Hash 上。然后我计算 Property1 上的 RSA 签名,Trailer.Hash 和 Trailer.Signature = null。我使用 DataContractSerializer 进行的二进制序列化。
问题是当我检索到哈希值时,它也很好地重新生成(加载时重新计算),但签名验证失败。尝试了很多方法,但似乎没有任何效果。
任何人都可以指出我想做的工作示例吗?我可以签署一个字符串并对其进行验证,但是使用二进制数据我无法让它工作。有关更详细的代码,请参阅我在 Github/
上的 Gist
public void Save(SampleObject model, byte[] cspBlob, string outFilename)
{
// Calculate the HMACSHA256 over a model with null Trailer section
CheckTrailer check = new CheckTrailer(); // empty keyed hash and empty signature
model.Check = null; // both HMAC & Signature are irrelevant for Save because we calculate them here
check.Trailer1 = model.GetKeyedHash<HMACSHA256>(GetKey());
DataContractSerializer serializer = new DataContractSerializer(model.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
model.Check = check;
// serialize with keyed hash and empty signature
serializer.WriteObject(memoryStream, model);
CspParameters cspparams = new CspParameters { Flags = CspProviderFlags.CreateEphemeralKey };
using (RSACryptoServiceProvider rsaSign = new RSACryptoServiceProvider(cspparams))
{
rsaSign.ImportCspBlob(cspBlob); // must be a key pair blob
if (rsaSign.PublicOnly)
{
throw new CryptographicException("Cannot sign with PUK");
}
check.Trailer2 = rsaSign.SignData(memoryStream, HashAlgorithm.Create(DSIG_HASH));
Console.WriteLine("\tDSIG: {0}", BitConverter.ToString(check.Trailer2));
}
}
// Place the computed signature
model.Check.Trailer2 = check.Trailer2;
// serialize
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new FileStream(outFilename, FileMode.Create, FileAccess.Write, FileShare.None))
{
formatter.Serialize(stream, model);
}
} // Save()
Can anybody point me to a WORKING example of what I want to do? I can sign a string and verify it but with binary data I cannot get it to work.
RSA 仅在二进制数据上定义,所以问题是您没有生成相同的二进制数据来签名和验证。
根据您的 Save 方法,问题是您签署的是空流,但验证的是非空流。
// New stream. Position=0, Length=0
using (MemoryStream memoryStream = new MemoryStream())
{
// Write some data. After this, Position=X, Length=X
serializer.WriteObject(memoryStream, model);
...
// RSA.SignData will read from Position until Length in the stream.
// Since Position=Length already, this means it's the same as calling
// SignData(Array.Empty<byte>)
check.Trailer2 = rsaSign.SignData(memoryStream, HashAlgorithm.Create(DSIG_HASH));
在调用 SignData 之前,您需要将内存流的位置重置为 0:
memoryStream.Position = 0;
check.Trailer2 = rsaSign.SignData(memoryStream, ...)
我正在尝试对二进制数据使用 RSA 签名和验证,但它不起作用,无论如何 RSA.VerifyData 总是 returns false。
基本上我有一个二进制序列化的对象:
public class MyObject {
public OtherClass Property1 { get; set; }
public Trailer Trailer { get; set; }
}
public class Trailer {
public byte[] Hash {get;set; } // Any hash
public byte[] Signature {get;set; }
}
基本上对象有自己的属性集,这里只有一个 (Property1)。然后我计算没有预告片的对象的哈希值并将其放在 Trailer.Hash 上。然后我计算 Property1 上的 RSA 签名,Trailer.Hash 和 Trailer.Signature = null。我使用 DataContractSerializer 进行的二进制序列化。
问题是当我检索到哈希值时,它也很好地重新生成(加载时重新计算),但签名验证失败。尝试了很多方法,但似乎没有任何效果。
任何人都可以指出我想做的工作示例吗?我可以签署一个字符串并对其进行验证,但是使用二进制数据我无法让它工作。有关更详细的代码,请参阅我在 Github/
上的 Gistpublic void Save(SampleObject model, byte[] cspBlob, string outFilename)
{
// Calculate the HMACSHA256 over a model with null Trailer section
CheckTrailer check = new CheckTrailer(); // empty keyed hash and empty signature
model.Check = null; // both HMAC & Signature are irrelevant for Save because we calculate them here
check.Trailer1 = model.GetKeyedHash<HMACSHA256>(GetKey());
DataContractSerializer serializer = new DataContractSerializer(model.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
model.Check = check;
// serialize with keyed hash and empty signature
serializer.WriteObject(memoryStream, model);
CspParameters cspparams = new CspParameters { Flags = CspProviderFlags.CreateEphemeralKey };
using (RSACryptoServiceProvider rsaSign = new RSACryptoServiceProvider(cspparams))
{
rsaSign.ImportCspBlob(cspBlob); // must be a key pair blob
if (rsaSign.PublicOnly)
{
throw new CryptographicException("Cannot sign with PUK");
}
check.Trailer2 = rsaSign.SignData(memoryStream, HashAlgorithm.Create(DSIG_HASH));
Console.WriteLine("\tDSIG: {0}", BitConverter.ToString(check.Trailer2));
}
}
// Place the computed signature
model.Check.Trailer2 = check.Trailer2;
// serialize
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new FileStream(outFilename, FileMode.Create, FileAccess.Write, FileShare.None))
{
formatter.Serialize(stream, model);
}
} // Save()
Can anybody point me to a WORKING example of what I want to do? I can sign a string and verify it but with binary data I cannot get it to work.
RSA 仅在二进制数据上定义,所以问题是您没有生成相同的二进制数据来签名和验证。
根据您的 Save 方法,问题是您签署的是空流,但验证的是非空流。
// New stream. Position=0, Length=0
using (MemoryStream memoryStream = new MemoryStream())
{
// Write some data. After this, Position=X, Length=X
serializer.WriteObject(memoryStream, model);
...
// RSA.SignData will read from Position until Length in the stream.
// Since Position=Length already, this means it's the same as calling
// SignData(Array.Empty<byte>)
check.Trailer2 = rsaSign.SignData(memoryStream, HashAlgorithm.Create(DSIG_HASH));
在调用 SignData 之前,您需要将内存流的位置重置为 0:
memoryStream.Position = 0;
check.Trailer2 = rsaSign.SignData(memoryStream, ...)