Skip to content

Commit

Permalink
Default Fabric Crypto Service Provider
Browse files Browse the repository at this point in the history
This change-set introduces a default implementation of the BCCSP
whose interfaces were introduced in https://gerrit.hyperledger.org/r/#/c/2027/
The implementation is based on the crypto/primitives package and provides
the following capabilities:
1. ecdsa key generation, sign, verify and public key marshalling,
2. HMAC,
3. Hashing,
4. AES key generation, encryption/decryption in CBC mode with PKCS7 padding.
This change-set comes in the context of:
https://jira.hyperledger.org/browse/FAB-354

Change-Id: Ica504c36756209ea540d010b4f48a801290a7be2
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Nov 3, 2016
1 parent b4473da commit cd43506
Show file tree
Hide file tree
Showing 7 changed files with 1,381 additions and 4 deletions.
7 changes: 3 additions & 4 deletions core/crypto/bccsp/bccsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,12 @@ type Key interface {
// false is this key is asymmetric
Symmetric() bool

// Private returns true if this key is an asymmetric private key,
// Private returns true if this key is a private key,
// false otherwise.
Private() bool

// PublicKey returns the corresponding public key if this key
// is an asymmetric private key. If this key is already public,
// PublicKey returns this key itself.
// PublicKey returns the corresponding public key part of an asymmetric public/private key pair.
// This method returns an error in symmetric key schemes.
PublicKey() (Key, error)
}

Expand Down
46 changes: 46 additions & 0 deletions core/crypto/bccsp/sw/aeskey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package sw

import (
"errors"

"github.com/hyperledger/fabric/core/crypto/bccsp"
"github.com/hyperledger/fabric/core/crypto/primitives"
)

type aesPrivateKey struct {
k []byte
exportable bool
}

// Bytes converts this key to its byte representation,
// if this operation is allowed.
func (k *aesPrivateKey) Bytes() (raw []byte, err error) {
if k.exportable {
return k.k, nil
}

return nil, errors.New("Not supported.")
}

// SKI returns the subject key identifier of this key.
func (k *aesPrivateKey) SKI() (ski []byte) {
return primitives.Hash(k.k)
}

// Symmetric returns true if this key is a symmetric key,
// false if this key is asymmetric
func (k *aesPrivateKey) Symmetric() bool {
return true
}

// Private returns true if this key is a private key,
// false otherwise.
func (k *aesPrivateKey) Private() bool {
return true
}

// PublicKey returns the corresponding public key part of an asymmetric public/private key pair.
// This method returns an error in symmetric key schemes.
func (k *aesPrivateKey) PublicKey() (bccsp.Key, error) {
return nil, errors.New("Cannot call this method on a symmetric key.")
}
53 changes: 53 additions & 0 deletions core/crypto/bccsp/sw/conf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package sw

import (
"errors"
"path/filepath"

"os"

"github.com/spf13/viper"
)

type config struct {
keystorePath string

configurationPathProperty string
}

func (conf *config) init() error {
conf.configurationPathProperty = "security.bccsp.default.keyStorePath"

// Check mandatory fields
var rootPath string
if err := conf.checkProperty(conf.configurationPathProperty); err != nil {
logger.Warning("'security.bccsp.default.keyStorePath' not set. Using the default directory [%s] for temporary files", os.TempDir())
rootPath = os.TempDir()
} else {
rootPath = viper.GetString(conf.configurationPathProperty)
}
logger.Infof("Root Path [%s]", rootPath)
// Set configuration path
rootPath = filepath.Join(rootPath, "crypto")

// Set ks path
conf.keystorePath = filepath.Join(rootPath, "ks")

return nil
}

func (conf *config) checkProperty(property string) error {
res := viper.GetString(property)
if res == "" {
return errors.New("Property not specified in configuration file. Please check that property is set: " + property)
}
return nil
}

func (conf *config) getKeyStorePath() string {
return conf.keystorePath
}

func (conf *config) getPathForAlias(alias, suffix string) string {
return filepath.Join(conf.getKeyStorePath(), alias+"_"+suffix)
}
86 changes: 86 additions & 0 deletions core/crypto/bccsp/sw/ecdsakey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package sw

import (
"crypto/ecdsa"
"crypto/x509"
"fmt"

"github.com/hyperledger/fabric/core/crypto/bccsp"
"github.com/hyperledger/fabric/core/crypto/primitives"
)

type ecdsaPrivateKey struct {
k *ecdsa.PrivateKey
}

// ToByte converts this key to its byte representation,
// if this operation is allowed.
func (k *ecdsaPrivateKey) Bytes() (raw []byte, err error) {
return
}

// SKI returns the subject key identifier of this key.
func (k *ecdsaPrivateKey) SKI() (ski []byte) {
raw, _ := primitives.PrivateKeyToDER(k.k)
// TODO: Error should not be thrown. Anyway, move the marshalling at initialization.

return primitives.Hash(raw)
}

// Symmetric returns true if this key is a symmetric key,
// false if this key is asymmetric
func (k *ecdsaPrivateKey) Symmetric() bool {
return false
}

// Private returns true if this key is a private key,
// false otherwise.
func (k *ecdsaPrivateKey) Private() bool {
return true
}

// PublicKey returns the corresponding public key part of an asymmetric public/private key pair.
// This method returns an error in symmetric key schemes.
func (k *ecdsaPrivateKey) PublicKey() (bccsp.Key, error) {
return &ecdsaPublicKey{&k.k.PublicKey}, nil
}

type ecdsaPublicKey struct {
k *ecdsa.PublicKey
}

// ToByte converts this key to its byte representation,
// if this operation is allowed.
func (k *ecdsaPublicKey) Bytes() (raw []byte, err error) {
raw, err = x509.MarshalPKIXPublicKey(k.k)
if err != nil {
return nil, fmt.Errorf("Failed marshalling key [%s]", err)
}
return
}

// SKI returns the subject key identifier of this key.
func (k *ecdsaPublicKey) SKI() (ski []byte) {
raw, _ := primitives.PublicKeyToPEM(k.k, nil)
// TODO: Error should not be thrown. Anyway, move the marshalling at initialization.

return primitives.Hash(raw)
}

// Symmetric returns true if this key is a symmetric key,
// false if this key is asymmetric
func (k *ecdsaPublicKey) Symmetric() bool {
return false
}

// Private returns true if this key is a private key,
// false otherwise.
func (k *ecdsaPublicKey) Private() bool {
return false
}

// PublicKey returns the corresponding public key part of an asymmetric public/private key pair.
// This method returns an error in symmetric key schemes.
func (k *ecdsaPublicKey) PublicKey() (bccsp.Key, error) {
return k, nil
}

0 comments on commit cd43506

Please sign in to comment.