【问题标题】:How to extract PKCS#1 signature from PKCS#7如何从 PKCS#7 中提取 PKCS#1 签名
【发布时间】:2019-08-06 07:07:30
【问题描述】:

我知道PKCS#7 = Certificate + Optional raw data + Signature in PKCS#1 format 我需要从 PKCS#7 签名中提取 PKCS#1,如何在 C# 中执行此操作。我可以使用充气城堡来做到这一点,这是我的实现 IE。将 PKCS#7 转换为 ASN.1 并采用最后一个序列,因为它是 PKCS#1

Asn1InputStream asn1 = new Asn1InputStream(pkcs7Stream);
Asn1Sequence sequence = (Asn1Sequence)asn1.ReadObject().ToAsn1Object();
var sequenceString = sequence.ToString();
var lastCommaIndex = sequenceString.LastIndexOf(",");
var pkcs1HexStr = sequenceString.Substring(lastCommaIndex + 3).Replace("]", string.Empty);

有没有其他优雅的方式来获取PKCS#1

【问题讨论】:

  • 根据您的代码,以及您的分隔符“,”和“]”,您的输入似乎不是二进制 pkcs7,而是 pkcs7 的文本表示
  • 来自 pkcs#7 流我将其转换为 ASN.1 序列并获取该序列的字符串形式并对其进行解析
  • 我知道 PKCS#7 = 证书 + 可选原始数据 + PKCS#1 格式的签名... 抱歉,这是一种极端的过度简化,并不是特别有用。 PKCS #7 的最佳实施文档是CMS,这应该是所有讨论的共同参考。现在,我可以假设您有兴趣处理的数据是内容类型为signed data 的单一签名者吗?

标签: c# bouncycastle pkcs#7 pkcs#1


【解决方案1】:

SignedCms 类可以为您执行此操作,.NET Core 2.1+ 或 .NET Framework 4.7.2+:

SignedCms cms = new SignedCms();
cms.Decode(message);
return cms.SignerInfos[0].GetSignature();

当然,假设您想要第一个签名者的签名。 (GetSignature方法需要net472+)

其他签名者或会签者也可以使用,只是通过对象模型的不同方面。

【讨论】:

  • 谢谢,@bartonis 这就像一个魅力,但是当我有时间戳,即 1.2.840.113549.1.9.16.2.14 timeStampToken (S/MIME Authenticated Attributes) 包含在签名中时,它会给出不同的值,因为在这种情况下会有两个签名数据,即 1.2.840.113549.1.7.2 signedData (PKCS #7)如何从时间戳令牌中存在的签名数据中获取签名。
  • @Prashanth Rfc3161TimestampToken.TryDecode(..); token.AsSignedCms() (现在您处于最近熟悉的领域)。仅限 .NET Core (2.1+)。 (完成之前的一些样本:github.com/dotnet/corefx/issues/24524#issuecomment-361337499
【解决方案2】:

感谢@bartonis 的帮助和指导

这是使用充气城堡的实现

public static byte[] GetRaw(byte[] input)
{
    SignerInfo signerInfo = GetSignerInfo(input);
    return signerInfo?.EncryptedDigest?.GetOctets();
}
private static SignerInfo GetSignerInfo(byte[] input)
{
    Asn1InputStream cmsInputStream = new Asn1InputStream(input);
    Asn1Object asn1Object = cmsInputStream.ReadObject();

    Asn1Sequence asn1Sequence = Asn1Sequence.GetInstance(asn1Object);
    SignedData signedData = GetSignedData(asn1Sequence);
    SignerInfo signerInfo = GetSignerInfo(signedData);
    if (signerInfo?.UnauthenticatedAttributes != null)
    {
        signedData = GetSignerInfo(signerInfo);
        signerInfo = GetSignerInfo(signedData);
    }
    return signerInfo;
}
private static SignerInfo GetSignerInfo(SignedData signedData)
{
    Asn1Encodable[] Asn1Encodables = signedData?.SignerInfos?.ToArray();
    if (Asn1Encodables != null)
    {
        if (Asn1Encodables.Length > 0)
        {
            SignerInfo signerInfo = SignerInfo.GetInstance(Asn1Encodables[0]);
            return signerInfo;
        }
    }
    return null;
}
private static SignedData GetSignedData(Asn1Sequence sequence)
{
    var rootContent = ContentInfo.GetInstance(sequence);
    var signedData = SignedData.GetInstance(rootContent.Content);
    return signedData;
}
private static SignedData GetSignerInfo(SignerInfo signerInfo)
{
    Asn1Encodable[] asn1Encodables = signerInfo.UnauthenticatedAttributes.ToArray();
    foreach (var asn1Encodable in asn1Encodables)
    {
        Asn1Sequence sequence = Asn1Sequence.GetInstance(asn1Encodable);
        DerObjectIdentifier OID = (DerObjectIdentifier)sequence[0];
        if (OID.Id == "1.2.840.113549.1.9.16.2.14")
        {
            Asn1Sequence newSequence =Asn1Sequence.GetInstance(Asn1Set.GetInstance(sequence[1])[0]);
            SignedData signedData = GetSignedData(newSequence);
            return signedData;
        }
    }
    return null;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多