How to COSE sign CBOR binary document using C# .Net core?

1.3k views Asked by At

How to COSE sign CBOR binary document using C# .Net core? I've found there is NuGet Package Com.AugustCellars.COSE But I'm new to this field and I can't find any examples, how to use it.

1

There are 1 answers

2
Arturs Mednis On BEST ANSWER

Finally I myself came up with working example

using Com.AugustCellars.COSE;
using PeterO.Cbor;
using System;
using System.Security.Cryptography.X509Certificates;

namespace Example
{
    class CoseSignExampleClass
    {


        public void RunCoseSigningExample()
        {
            string exampleJson = "{\"name\":\"example\"}";
            CBORObject exampleCbor = CBORObject.FromJSONString(exampleJson);
            byte[] cborBytes = exampleCbor.EncodeToBytes();


            // signedCbor now is COSE signed CBOR document
            byte[] signedCbor = CoseSign(cborBytes);
            

            // one can check verify signature with public key
            bool validSignature = ValidateCoseSignature(signedCbor);


            // one can get back document
            byte[] extractedCborBytes = GetCoseContent(signedCbor);
            PeterO.Cbor.CBORObject decodedCborData = PeterO.Cbor.CBORObject.DecodeFromBytes(extractedCborBytes);

            string output = decodedCborData.ToString();
        }



        byte[] CoseSign(byte[] cborBytes)
        {
            OneKey signKeyPrivate = GetSignPrivateKey();

            Sign1Message signMessage = new Sign1Message();
            signMessage.AddAttribute(HeaderKeys.Algorithm, AlgorithmValues.ECDSA_256, Attributes.PROTECTED);

            signMessage.SetContent(cborBytes);

            signMessage.Sign(signKeyPrivate);
            byte[] rgbMsg = signMessage.EncodeToBytes();

            return rgbMsg;
        }

        static OneKey GetSignPrivateKey()
        {
            /* 
             * privateKeyString is PKCS8 key without starting and ending tags
             * "-----BEGIN PRIVATE KEY-----"
             * "-----END PRIVATE KEY-----"
             */

            string privateKeyString = @"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfK2MnqJPUzuSy2tB
t7kjH5OGeP8O38dkOMXmKNfVynuhRANCAASPTR2m+kV/3Xuxh8tjRxJn0v//Y/yS
Tl+LHlBowq7v+i6sGpJXEfPYbBc+tGZBL9MXX6WMV1I0QCMykqLyKwD3";

            byte[] Pkcs8PrivateKey = Convert.FromBase64String(privateKeyString);
            OneKey cnKeyPrivate = OneKey.FromPkcs8(Pkcs8PrivateKey);

            return cnKeyPrivate;
        }

        byte[] GetCoseContent(byte[] coseDocument)
        {
            Sign1Message msg = (Sign1Message)Message.DecodeFromBytes(coseDocument, Tags.Sign1);
            return msg.GetContent();
        }

        bool ValidateCoseSignature(byte[] coseDocument)
        {
            Sign1Message msg = (Sign1Message)Message.DecodeFromBytes(coseDocument, Tags.Sign1);
            OneKey cnKeyPublic = GetSignPublicKey();
            return msg.Validate(cnKeyPublic);
        }

        static OneKey GetSignPublicKey()
        {
            /* 
             * publicKeyString is Pem public cert without starting and ending tags
             * "-----BEGIN CERTIFICATE-----"
             * "-----END CERTIFICATE-----"
             */

            string publicKeyString = @"MIICTzCCAfWgAwIBAgIUJgt2piBt1qKUVWqjs/bhkSTpbscwCgYIKoZIzj0EAwIw
ZDELMAkGA1UEBhMCTFYxLTArBgNVBAoMJE5hY2lvbsOEwoFsYWlzIFZlc2Vsw4TC
q2JhcyBkaWVuZXN0czEMMAoGA1UECwwDVExTMRgwFgYDVQQDDA9UTFMgREdDIExW
IFRlc3QwHhcNMjEwNTE4MTA0OTA1WhcNMjMwNTE4MTA0OTA1WjBkMQswCQYDVQQG
EwJMVjEtMCsGA1UECgwkTmFjaW9uw4TCgWxhaXMgVmVzZWzDhMKrYmFzIGRpZW5l
c3RzMQwwCgYDVQQLDANUTFMxGDAWBgNVBAMMD1RMUyBER0MgTFYgVGVzdDBZMBMG
ByqGSM49AgEGCCqGSM49AwEHA0IABI9NHab6RX/de7GHy2NHEmfS//9j/JJOX4se
UGjCru/6LqwaklcR89hsFz60ZkEv0xdfpYxXUjRAIzKSovIrAPejgYQwgYEwDgYD
VR0PAQH/BAQDAgeAMB0GA1UdDgQWBBQO528ONBxapB+St9et1oYQySBhjjA3BgNV
HR8EMDAuMCygKqAohiZodHRwOi8vY3JsLm5wa2QubmwvQ1JMcy9OTEQtSGVhbHRo
LmNybDAXBgNVHSUEEDAOBgwrBgEEAQCON49lAQEwCgYIKoZIzj0EAwIDSAAwRQIg
Bc50+qIVI+IUQrUJQdYywW1PhNEyW5VxiT3HvGxyJaACIQD+ze+4r5GUcuWdNpPP
lFcSLRBj/MNpO6sl8h2Y5h/c8g==";

            byte[] publicKeyData = Convert.FromBase64String(publicKeyString);

            byte[] certData;

            using (X509Certificate2 x509Cert = new X509Certificate2(publicKeyData))
                certData = x509Cert.GetRawCertData();


            OneKey keyPublic = OneKey.FromX509(certData);

            return keyPublic;
        }
    }
}