-
Notifications
You must be signed in to change notification settings - Fork 0
/
cryptoutils.go
142 lines (113 loc) · 4.18 KB
/
cryptoutils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package cryptoutil
import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"encoding/pem"
"github.com/aiguo186/fabric-sdk-go-gm/internal/github.com/tjfoc/gmsm/sm2"
tls "github.com/aiguo186/fabric-sdk-go-gm/internal/github.com/tjfoc/gmtls"
"io"
"github.com/aiguo186/fabric-sdk-go-gm/pkg/common/logging"
"github.com/aiguo186/fabric-sdk-go-gm/pkg/common/providers/core"
"github.com/pkg/errors"
factory "github.com/aiguo186/fabric-sdk-go-gm/internal/github.com/aiguo186/fabric-ca/sdkpatch/cryptosuitebridge"
)
var logger = logging.NewLogger("fabsdk/core")
// GetPrivateKeyFromCert will return private key represented by SKI in cert's public key
func GetPrivateKeyFromCert(cert []byte, cs core.CryptoSuite) (core.Key, error) {
// get the public key in the right format
certPubK, err := GetPublicKeyFromCert(cert, cs)
if err != nil {
return nil, errors.WithMessage(err, "Failed to import certificate's public key")
}
if certPubK == nil || certPubK.SKI() == nil {
return nil, errors.New("Failed to get SKI")
}
// Get the key given the SKI value
key, err := cs.GetKey(certPubK.SKI())
if err != nil {
return nil, errors.WithMessage(err, "Could not find matching key for SKI")
}
if key != nil && !key.Private() {
return nil, errors.Errorf("Found key is not private, SKI: %s", certPubK.SKI())
}
return key, nil
}
// GetPublicKeyFromCert will return public key the from cert
func GetPublicKeyFromCert(cert []byte, cs core.CryptoSuite) (core.Key, error) {
dcert, _ := pem.Decode(cert)
if dcert == nil {
return nil, errors.Errorf("Unable to decode cert bytes [%v]", cert)
}
x509Cert, err := sm2.ParseCertificate(dcert.Bytes)
if err != nil {
return nil, errors.Errorf("Unable to parse cert from decoded bytes: %s", err)
}
// get the public key in the right format
key, err := cs.KeyImport(x509Cert, factory.GetX509PublicKeyImportOpts(true))
if err != nil {
return nil, errors.WithMessage(err, "Failed to import certificate's public key")
}
return key, nil
}
// X509KeyPair will return cer/key pair used for mutual TLS
func X509KeyPair(certPEMBlock []byte, pk core.Key, cs core.CryptoSuite) (tls.Certificate, error) {
fail := func(err error) (tls.Certificate, error) { return tls.Certificate{}, err }
var cert tls.Certificate
for {
var certDERBlock *pem.Block
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
} else {
logger.Debugf("Skipping block type: %s", certDERBlock.Type)
}
}
if len(cert.Certificate) == 0 {
return fail(errors.New("No certs available from bytes"))
}
// We are parsing public key for TLS to find its type
x509Cert, err := sm2.ParseCertificate(cert.Certificate[0])
if err != nil {
return fail(err)
}
switch x509Cert.PublicKey.(type) {
case *rsa.PublicKey:
cert.PrivateKey = &PrivateKey{cs, pk, &rsa.PublicKey{}}
case *ecdsa.PublicKey:
cert.PrivateKey = &PrivateKey{cs, pk, &ecdsa.PublicKey{}}
default:
return fail(errors.New("tls: unknown public key algorithm"))
}
return cert, nil
}
//PrivateKey is signer implementation for golang client TLS
type PrivateKey struct {
cryptoSuite core.CryptoSuite
key core.Key
publicKey crypto.PublicKey
}
// Public returns the public key corresponding to private key
func (priv *PrivateKey) Public() crypto.PublicKey {
return priv.publicKey
}
// Sign signs msg with priv, reading randomness from rand. If opts is a
// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
// be used. This method is intended to support keys where the private part is
// kept in, for example, a hardware module.
func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
if priv.cryptoSuite == nil {
return nil, errors.New("Crypto suite not set")
}
if priv.key == nil {
return nil, errors.New("Private key not set")
}
return priv.cryptoSuite.Sign(priv.key, msg, opts)
}