【问题标题】:Cannot get my RSA signature/verifiction on BINARY data to work. Any working examples?无法让我对 BINARY 数据的 RSA 签名/验证工作。任何工作示例?
【发布时间】:2017-08-08 14:12:29
【问题描述】:

我正在尝试对二进制数据使用 RSA 签名和验证,但它不起作用,无论如何 RSA.VerifyData 总是返回 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、Trailer.Hash 和 Trailer.Signature = null 计算 RSA 签名。我使用 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()

【问题讨论】:

    标签: .net cryptography datacontractserializer signing binary-serialization


    【解决方案1】:

    谁能指出我想做的工作示例?我可以签署一个字符串并对其进行验证,但使用二进制数据我无法让它工作。

    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, ...)
    

    【讨论】:

    • 感谢一百万,我怎么能忽略这样一个基本错误!谢谢一百万!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    相关资源
    最近更新 更多