Reputation: 527
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
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
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