forked from hyperledger/fabric
/
p11key.go
62 lines (49 loc) · 1.45 KB
/
p11key.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
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package pkcs11
import (
"crypto"
"crypto/ecdsa"
"encoding/asn1"
"fmt"
"io"
"math/big"
"github.com/miekg/pkcs11"
)
// P11ECDSAKey test implementation of crypto.Signer.
type P11ECDSAKey struct {
ctx *pkcs11.Ctx
session pkcs11.SessionHandle
publicKey *ecdsa.PublicKey
privateKeyHandle pkcs11.ObjectHandle
}
// Public returns the corresponding public key for the
// private key.
func (k *P11ECDSAKey) Public() crypto.PublicKey {
return k.publicKey
}
// Sign implements crypto.Signer Sign(). Signs the digest the with the private key and returns a byte signature.
func (k *P11ECDSAKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
if len(digest) != opts.HashFunc().Size() {
return nil, fmt.Errorf("digest length does not equal hash function length")
}
mech := []*pkcs11.Mechanism{
pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil),
}
err = k.ctx.SignInit(k.session, mech, k.privateKeyHandle)
if err != nil {
return nil, fmt.Errorf("sign init failed: %s", err)
}
signature, err = k.ctx.Sign(k.session, digest)
if err != nil {
return nil, fmt.Errorf("sign failed: %s", err)
}
type ECDSASignature struct{ R, S *big.Int }
R := new(big.Int)
S := new(big.Int)
R.SetBytes(signature[0 : len(signature)/2])
S.SetBytes(signature[len(signature)/2:])
return asn1.Marshal(ECDSASignature{R: R, S: S})
}