1 Star 0 Fork 0

peter / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
impl.go 7.29 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package pkcs11
import (
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"os"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/sw"
"github.com/hyperledger/fabric/common/flogging"
"github.com/miekg/pkcs11"
"github.com/pkg/errors"
)
var (
logger = flogging.MustGetLogger("bccsp_p11")
sessionCacheSize = 10
)
// New WithParams returns a new instance of the software-based BCCSP
// set at the passed security level, hash family and KeyStore.
func New(opts PKCS11Opts, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) {
// Init config
conf := &config{}
err := conf.setSecurityLevel(opts.SecLevel, opts.HashFamily)
if err != nil {
return nil, errors.Wrapf(err, "Failed initializing configuration")
}
swCSP, err := sw.NewWithParams(opts.SecLevel, opts.HashFamily, keyStore)
if err != nil {
return nil, errors.Wrapf(err, "Failed initializing fallback SW BCCSP")
}
// Check KeyStore
if keyStore == nil {
return nil, errors.New("Invalid bccsp.KeyStore instance. It must be different from nil")
}
lib := opts.Library
pin := opts.Pin
label := opts.Label
ctx, slot, session, err := loadLib(lib, pin, label)
if err != nil {
return nil, errors.Wrapf(err, "Failed initializing PKCS11 library %s %s",
lib, label)
}
sessions := make(chan pkcs11.SessionHandle, sessionCacheSize)
csp := &impl{swCSP, conf, keyStore, ctx, sessions, slot, lib, opts.SoftVerify, opts.Immutable}
csp.returnSession(*session)
return csp, nil
}
type impl struct {
bccsp.BCCSP
conf *config
ks bccsp.KeyStore
ctx *pkcs11.Ctx
sessions chan pkcs11.SessionHandle
slot uint
lib string
softVerify bool
//Immutable flag makes object immutable
immutable bool
}
// KeyGen generates a key using opts.
func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) {
// Validate arguments
if opts == nil {
return nil, errors.New("Invalid Opts parameter. It must not be nil")
}
// Parse algorithm
switch opts.(type) {
case *bccsp.ECDSAKeyGenOpts:
ski, pub, err := csp.generateECKey(csp.conf.ellipticCurve, opts.Ephemeral())
if err != nil {
return nil, errors.Wrapf(err, "Failed generating ECDSA key")
}
k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
case *bccsp.ECDSAP256KeyGenOpts:
ski, pub, err := csp.generateECKey(oidNamedCurveP256, opts.Ephemeral())
if err != nil {
return nil, errors.Wrapf(err, "Failed generating ECDSA P256 key")
}
k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
case *bccsp.ECDSAP384KeyGenOpts:
ski, pub, err := csp.generateECKey(oidNamedCurveP384, opts.Ephemeral())
if err != nil {
return nil, errors.Wrapf(err, "Failed generating ECDSA P384 key")
}
k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
default:
return csp.BCCSP.KeyGen(opts)
}
return k, nil
}
// KeyImport imports a key from its raw representation using opts.
// The opts argument should be appropriate for the primitive used.
func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) {
// Validate arguments
if raw == nil {
return nil, errors.New("Invalid raw. Cannot be nil")
}
if opts == nil {
return nil, errors.New("Invalid Opts parameter. It must not be nil")
}
switch opts.(type) {
case *bccsp.X509PublicKeyImportOpts:
x509Cert, ok := raw.(*x509.Certificate)
if !ok {
return nil, errors.New("[X509PublicKeyImportOpts] Invalid raw material. Expected *x509.Certificate")
}
pk := x509Cert.PublicKey
switch pk.(type) {
case *ecdsa.PublicKey:
return csp.KeyImport(pk, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
case *rsa.PublicKey:
return csp.KeyImport(pk, &bccsp.RSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
default:
return nil, errors.New("Certificate's public key type not recognized. Supported keys: [ECDSA, RSA]")
}
default:
return csp.BCCSP.KeyImport(raw, opts)
}
}
// GetKey returns the key this CSP associates to
// the Subject Key Identifier ski.
func (csp *impl) GetKey(ski []byte) (bccsp.Key, error) {
pubKey, isPriv, err := csp.getECKey(ski)
if err == nil {
if isPriv {
return &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pubKey}}, nil
}
return &ecdsaPublicKey{ski, pubKey}, nil
}
return csp.BCCSP.GetKey(ski)
}
// Sign signs digest using key k.
// The opts argument should be appropriate for the primitive used.
//
// Note that when a signature of a hash of a larger message is needed,
// the caller is responsible for hashing the larger message and passing
// the hash (as digest).
func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]byte, error) {
// Validate arguments
if k == nil {
return nil, errors.New("Invalid Key. It must not be nil")
}
if len(digest) == 0 {
return nil, errors.New("Invalid digest. Cannot be empty")
}
// Check key type
switch k.(type) {
case *ecdsaPrivateKey:
return csp.signECDSA(*k.(*ecdsaPrivateKey), digest, opts)
default:
return csp.BCCSP.Sign(k, digest, opts)
}
}
// Verify verifies signature against key k and digest
func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) {
// Validate arguments
if k == nil {
return false, errors.New("Invalid Key. It must not be nil")
}
if len(signature) == 0 {
return false, errors.New("Invalid signature. Cannot be empty")
}
if len(digest) == 0 {
return false, errors.New("Invalid digest. Cannot be empty")
}
// Check key type
switch k.(type) {
case *ecdsaPrivateKey:
return csp.verifyECDSA(k.(*ecdsaPrivateKey).pub, signature, digest, opts)
case *ecdsaPublicKey:
return csp.verifyECDSA(*k.(*ecdsaPublicKey), signature, digest, opts)
default:
return csp.BCCSP.Verify(k, signature, digest, opts)
}
}
// Encrypt encrypts plaintext using key k.
// The opts argument should be appropriate for the primitive used.
func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) ([]byte, error) {
// TODO: Add PKCS11 support for encryption, when fabric starts requiring it
return csp.BCCSP.Encrypt(k, plaintext, opts)
}
// Decrypt decrypts ciphertext using key k.
// The opts argument should be appropriate for the primitive used.
func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) ([]byte, error) {
return csp.BCCSP.Decrypt(k, ciphertext, opts)
}
// FindPKCS11Lib IS ONLY USED FOR TESTING
// This is a convenience function. Useful to self-configure, for tests where usual configuration is not
// available
func FindPKCS11Lib() (lib, pin, label string) {
//FIXME: Till we workout the configuration piece, look for the libraries in the familiar places
lib = os.Getenv("PKCS11_LIB")
if lib == "" {
pin = "98765432"
label = "ForFabric"
possibilities := []string{
"/usr/lib/softhsm/libsofthsm2.so", //Debian
"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
"/usr/lib/s390x-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
"/usr/lib/powerpc64le-linux-gnu/softhsm/libsofthsm2.so", //Power
"/usr/local/Cellar/softhsm/2.1.0/lib/softhsm/libsofthsm2.so", //MacOS
}
for _, path := range possibilities {
if _, err := os.Stat(path); !os.IsNotExist(err) {
lib = path
break
}
}
} else {
pin = os.Getenv("PKCS11_PIN")
label = os.Getenv("PKCS11_LABEL")
}
return lib, pin, label
}
1
https://gitee.com/peter_code_git/fabric.git
git@gitee.com:peter_code_git/fabric.git
peter_code_git
fabric
fabric
v1.4.0-rc2

搜索帮助