...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package x509tools
18
19 import (
20 "crypto"
21 "crypto/ecdsa"
22 "crypto/rand"
23 "crypto/rsa"
24 "crypto/sha1"
25 "crypto/x509"
26 "crypto/x509/pkix"
27 "encoding/asn1"
28 "errors"
29 "io"
30 "math/big"
31 )
32
33
34 func MakeSerial() *big.Int {
35 blob := make([]byte, 12)
36 if _, err := io.ReadFull(rand.Reader, blob); err != nil {
37 return nil
38 }
39 return new(big.Int).SetBytes(blob)
40 }
41
42
43 func X509SignatureAlgorithm(pub crypto.PublicKey) x509.SignatureAlgorithm {
44 switch pub.(type) {
45 case *rsa.PublicKey:
46 if ArgRSAPSS {
47 return x509.SHA256WithRSAPSS
48 }
49 return x509.SHA256WithRSA
50 case *ecdsa.PublicKey:
51 return x509.ECDSAWithSHA256
52 default:
53 return x509.UnknownSignatureAlgorithm
54 }
55 }
56
57 type pkixPublicKey struct {
58 Algo pkix.AlgorithmIdentifier
59 BitString asn1.BitString
60 }
61
62
63 func SubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
64 der, err := x509.MarshalPKIXPublicKey(pub)
65 if err != nil {
66 return nil, err
67 }
68
69 var pki pkixPublicKey
70 if rest, err := asn1.Unmarshal(der, &pki); err != nil {
71 return nil, err
72 } else if len(rest) != 0 {
73 return nil, errors.New("trailing garbage on public key")
74 }
75 digest := sha1.Sum(pki.BitString.RightAlign())
76 return digest[:], nil
77 }
78
79
80 func SameKey(pub1, pub2 interface{}) bool {
81 if privkey, ok := pub1.(crypto.Signer); ok {
82 pub1 = privkey.Public()
83 }
84 if privkey, ok := pub2.(crypto.Signer); ok {
85 pub2 = privkey.Public()
86 }
87 switch key1 := pub1.(type) {
88 case *rsa.PublicKey:
89 key2, ok := pub2.(*rsa.PublicKey)
90 return ok && key1.E == key2.E && key1.N.Cmp(key2.N) == 0
91 case *ecdsa.PublicKey:
92 key2, ok := pub2.(*ecdsa.PublicKey)
93 return ok && key1.X.Cmp(key2.X) == 0 && key1.Y.Cmp(key2.Y) == 0
94 default:
95 return false
96 }
97 }
98
99
100 func Verify(pub interface{}, hash crypto.Hash, hashed []byte, sig []byte) error {
101 switch pubk := pub.(type) {
102 case *rsa.PublicKey:
103 return rsa.VerifyPKCS1v15(pubk, hash, hashed, sig)
104 case *ecdsa.PublicKey:
105 esig, err := UnmarshalEcdsaSignature(sig)
106 if err != nil {
107 return err
108 }
109 if !ecdsa.Verify(pubk, hashed, esig.R, esig.S) {
110 return errors.New("ECDSA verification failed")
111 }
112 return nil
113 }
114 return errors.New("unsupported public key algorithm")
115 }
116
117
118 func GetPublicKeyAlgorithm(key interface{}) x509.PublicKeyAlgorithm {
119 if privkey, ok := key.(crypto.Signer); ok {
120 key = privkey.Public()
121 }
122 switch key.(type) {
123 case *rsa.PublicKey:
124 return x509.RSA
125 case *ecdsa.PublicKey:
126 return x509.ECDSA
127 default:
128 return x509.UnknownPublicKeyAlgorithm
129 }
130 }
131
View as plain text