Search code examples
c#opensslx509certificate2smime

Different S/MIME signature between OpenSSL and C#


I'm trying to use an OpenSSL code in my .Net program. Here's the code:

openssl pkcs12 -in "My PassKit Cert.p12" -clcerts -nokeys -out certificate.pem
openssl pkcs12 -in "My PassKit Cert.p12" -nocerts -out key.pem
smime -binary -sign -signer certificate.pem -inkey key.pem -in manifest.json -out signature -outform DER

I tried to use .Net OpenSSL, but I absolutely have no idea how to use it, and I couldn't find a good documentation for it. I decided to use .Net to perform the same sign process, here's the code:

var dataToSign = System.IO.File.ReadAllBytes(filePathToSign);
ContentInfo contentInfo = new ContentInfo(dataToSign);

X509Certificate2 signerCert = new X509Certificate2(System.IO.File.ReadAllBytes(signerPfxCertPath), signerPfxCertPassword);

var signedCms = new SignedCms(contentInfo, true);
var signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, signerCert);

signer.IncludeOption = X509IncludeOption.EndCertOnly;
signedCms.ComputeSignature(signer);

var myCmsMessage = signedCms.Encode();

var buf = Encoding.Convert(Encoding.UTF7, Encoding.UTF8, myCmsMessage);

return Encoding.UTF8.GetString(buf, 0, buf.Length);

But the results between C# and OpenSSL are not the same. Can someone please help me out?

Thanks in advance!


Solution

  • I got this working in the end!

    First, you must go here, and install the apple ROOT cert:

    http://www.apple.com/certificateauthority/

    (it's the first one). Install it into your trusted root authority. A Mac already has this.

    Second, install the developer cert as a trusted root authority, which is in the developer portal, where you go to add devices, make passkit keys, all that

    https://developer.apple.com/ios/manage/certificates/team/index.action

    (you need a login for that)

    then you need to generate your passkit key in the dev portal, download it, install it on your mac, then export it WITH the private key as a .p12 file.

    you can then move this file to the windows machine and use it. I used this code, after generating the manifest:

    var cert = new X509Certificate2(@"path-to-your.p12", "password");
    
    var buffer = File.ReadAllBytes(Path.Combine(basePath, "manifest.json"));
    
    ContentInfo cont = new ContentInfo(buffer);
    var cms = new SignedCms(cont, true);
    var signer = new CmsSigner(SubjectIdentifierType.SubjectKeyIdentifier, cert);
    
    signer.IncludeOption = X509IncludeOption.ExcludeRoot;
    
    cms.ComputeSignature(signer);
    
    var myCmsMessage = cms.Encode();
    
    
    File.WriteAllBytes(Path.Combine(basePath, "signature"), myCmsMessage);
    

    Sorry, this is rather messy code, but it works :)

    Don't forget to set

    "passTypeIdentifier" : "pass.com.yourcompany.NameOfYourPass", "teamIdentifier" : "YOUR TEAM ID",

    in the pass.json!