...
1 package cosesign1
2
3 import (
4 "crypto"
5 "crypto/rand"
6 "crypto/x509"
7 "encoding/pem"
8 "fmt"
9 "io"
10
11 "github.com/sirupsen/logrus"
12
13 "github.com/veraison/go-cose"
14 )
15
16 func pem2der(chainPem []byte) []byte {
17 block, rest := pem.Decode(chainPem)
18 if block != nil && block.Bytes != nil {
19 r := block.Bytes
20
21 for len(rest) != 0 {
22 block, rest = pem.Decode(rest)
23 if block != nil && block.Bytes != nil {
24 r = append(r, block.Bytes...)
25 }
26 }
27 return r
28 }
29 return nil
30 }
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 func CreateCoseSign1(payloadBlob []byte, issuer string, feed string, contentType string, chainPem []byte, keyPem []byte, saltType string, algo cose.Algorithm) (result []byte, err error) {
47 var signingKey any
48 keyDer, _ := pem.Decode(keyPem)
49 if keyDer == nil {
50 return nil, fmt.Errorf("failed to find key in PEM")
51 }
52 var keyBytes = keyDer.Bytes
53
54
55 signingKey, err = x509.ParseECPrivateKey(keyBytes)
56 if err == nil {
57 logrus.WithField("key", signingKey).Debug("parsed EC signing (private) key")
58 }
59
60 if err != nil {
61 signingKey, err = x509.ParsePKCS8PrivateKey(keyBytes)
62 if err == nil {
63 logrus.WithField("key", signingKey).Debug("parsed PKCS8 signing (private) key")
64 }
65 }
66
67 if err != nil {
68 signingKey, err = x509.ParsePKCS1PrivateKey(keyBytes)
69 if err == nil {
70 logrus.WithField("key", signingKey).Debug("parsed PKCS1 signing (private) key")
71 }
72 }
73
74 if err != nil {
75 logrus.WithError(err).Debug("failed to decode a key")
76 return nil, err
77 }
78
79 chainDER := pem2der(chainPem)
80 if chainDER == nil {
81 return nil, fmt.Errorf("failed to parse chainPem")
82 }
83
84 var chainCerts []*x509.Certificate
85 chainCerts, err = x509.ParseCertificates(chainDER)
86
87 if err == nil {
88 logrus.WithField("leaf cert", fmt.Sprintf("%v", *chainCerts[0])).Debug("parsed cert chain for leaf")
89 } else {
90 logrus.WithError(err).Debug("cert parsing failed")
91 return nil, err
92 }
93
94 chainDERArray := make([][]byte, len(chainCerts))
95 for i, cert := range chainCerts {
96 chainDERArray[i] = cert.Raw
97 }
98
99 var saltReader io.Reader
100 if saltType == "rand" {
101 saltReader = rand.Reader
102 } else {
103 saltReader = NewFixedReader(0)
104 }
105
106 cryptoSigner, ok := signingKey.(crypto.Signer)
107 if !ok {
108 return nil, fmt.Errorf("signingKey must be of type crypto.Signer")
109 }
110
111 var signer cose.Signer
112 signer, err = cose.NewSigner(algo, cryptoSigner)
113 if err != nil {
114 logrus.WithError(err).Error("failed to initialize cose signer")
115 return nil, err
116 }
117
118
119 headers := cose.Headers{
120 Protected: cose.ProtectedHeader{
121 cose.HeaderLabelAlgorithm: algo,
122 cose.HeaderLabelContentType: contentType,
123 cose.HeaderLabelX5Chain: chainDERArray,
124 },
125 }
126
127
128
129 if len(issuer) > 0 {
130 headers.Protected["iss"] = issuer
131 }
132 if len(feed) > 0 {
133 headers.Protected["feed"] = feed
134 }
135
136 result, err = cose.Sign1(saltReader, signer, headers, payloadBlob, nil)
137 if err != nil {
138 logrus.WithError(err).Debug("failed to create cose.Sign1")
139 return nil, err
140 }
141
142 return result, nil
143 }
144
View as plain text