Prashanth
Prashanth

Reputation: 527

How to extract PKCS#1 signature from PKCS#7

I know that PKCS#7 = Certificate + Optional raw data + Signature in PKCS#1 format I need to extract PKCS#1 from a PKCS#7 signature how can I do this in C#. Can I use the bouncy castle to do this, Here is my implementation ie. to convert PKCS#7 to ASN.1 and to take the last sequence as it is 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);

Is there any other eligant way to obtain PKCS#1

Upvotes: 4

Views: 2662

Answers (2)

Prashanth
Prashanth

Reputation: 527

Thanks, @bartonis for the help and guidance

Here is implementation using bouncy castle

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;
}

Upvotes: 0

bartonjs
bartonjs

Reputation: 33098

The SignedCms class can do this for you, .NET Core 2.1+ or .NET Framework 4.7.2+:

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

Assuming you want the signature from the first signer, of course. (The GetSignature method is what requires net472+)

Other signers or countersigners would also be available, just through different aspects of the object model.

Upvotes: 5

Related Questions