Skip to content

Commit

Permalink
Added Crypto Readme
Browse files Browse the repository at this point in the history
  • Loading branch information
tfn18001 committed Apr 20, 2022
1 parent 12d7972 commit ef15d9b
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 22 deletions.
24 changes: 24 additions & 0 deletions CTng/crypto/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Cryptography Implementations

## Contents:
- `types.go`: type declarations with descriptions for all the files below.
- `bls.go`: implementation of k-of-n threshold signatures using a BLS library.
- `rsa.go`: Creates slightly simplified+application specific RSA functions from go's "crypto/rsa" library.
- `hash.go`: functions for hashing of data using a variety of schemes.
- `generate_crypto.go`: Given security constraints/requirements and the names of each entity in the network, generate BLS and RSA keys, and create and store CryptoConfig files for each entity.

## crypto_config.go:
- `CryptoConfig` is an object that contains all the cryptographic information for an entity to use
- e.x: Mappings to public keys, Private keys, signature schemes being utilized, etc.
- For convenience, methods are defined for this object which use the information stored within the config to Hash, Sign, and Verify signatures.
- Thus, all cryptographic actions are condensed to a single object.

## Signature Object Format:
- `RSASig`, `ThresholdSig`, and `SigFragment` are objects of signatures bundled with the signing entity. (BLS for the latter two).
- While this information is typically contained within a gossip object's Signer Field, there currently isn't a way to store multiple signers of data in a gossip object. Thus, this implementation is integral to the `ThresholdSig` Type.

## cyrpto_test.go
The following tests are included:
1. Hash function test
2. K-of-n BLS key generation + signing/verifying with different subsets
3. IO function tests: Writes and then reads a cryptoconfig and verifies functionality
3 changes: 1 addition & 2 deletions CTng/crypto/bls.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ func ThresholdAggregate(sigs []SigFragment, threshold int) (ThresholdSig, error)
return aggregate, nil
}

// Verify a threshold signature.
// Verify an aggregated threshold signature against the message and the public keys
func (sig ThresholdSig) Verify(msg string, pubs *BlsPublicMap) bool {
// Verify the aggregated signature against the message and the public keys
// Construct the list of public keys
pubList := make([]bls.PublicKey, len(sig.IDs))
for i := range sig.IDs {
Expand Down
10 changes: 10 additions & 0 deletions CTng/crypto/crypto_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type CryptoConfigInterface interface {
FragmentVerify(string, SigFragment) error
}

// Hash a message using the configured hash scheme.
func (c *CryptoConfig) Hash(msg []byte) ([]byte, error) {
if c.HashScheme == SHA256 {
return GenerateSHA256(msg)
Expand All @@ -26,13 +27,16 @@ func (c *CryptoConfig) Hash(msg []byte) ([]byte, error) {
return nil, errors.New("Hash Scheme not supported")
}

// Sign a message using the configured "normal signature" scheme.
// Note: This is not a threshold signature/threshold signature fragment.
func (c *CryptoConfig) Sign(msg []byte) (RSASig, error) {
if c.SignScheme == "rsa" {
return RSASign(msg, &c.RSAPrivateKey, c.SelfID)
}
return RSASig{}, errors.New("Sign Scheme not supported")
}

// Verify a message using the configured "normal signature" scheme, and the stored public keys.
func (c *CryptoConfig) Verify(msg []byte, sig RSASig) error {
if c.SignScheme == "rsa" {
pub := c.SignaturePublicMap[sig.ID]
Expand All @@ -41,6 +45,7 @@ func (c *CryptoConfig) Verify(msg []byte, sig RSASig) error {
return errors.New("Sign Scheme not supported")
}

// Sign a message to make a keyfragment using the configured "threshold signature" scheme.
func (c *CryptoConfig) ThresholdSign(msg string) (SigFragment, error) {
if c.ThresholdScheme == "bls" {
return ThresholdSign(msg, &c.ThresholdSecretKey, c.SelfID), nil
Expand All @@ -49,6 +54,7 @@ func (c *CryptoConfig) ThresholdSign(msg string) (SigFragment, error) {
return SigFragment{}, errors.New("Threshold Scheme not supported")
}

// Aggregate a list of threshold signature fragments to make a threshold signature.
func (c *CryptoConfig) ThresholdAggregate(sigs []SigFragment) (ThresholdSig, error) {
if c.ThresholdScheme == "bls" {
sig, err := ThresholdAggregate(sigs, c.Threshold)
Expand All @@ -61,6 +67,8 @@ func (c *CryptoConfig) ThresholdAggregate(sigs []SigFragment) (ThresholdSig, err
return ThresholdSig{}, errors.New("Threshold Scheme not supported")
}

// Verify a threshold signature using the configured "threshold signature" scheme, and the stored public keys.
// Uses the keys stored in the CryptoConfig struct to verify the signature.
func (c *CryptoConfig) ThresholdVerify(msg string, sig ThresholdSig) error {
if c.ThresholdScheme == "bls" {
if sig.Verify(msg, &c.ThresholdPublicMap) {
Expand All @@ -72,6 +80,8 @@ func (c *CryptoConfig) ThresholdVerify(msg string, sig ThresholdSig) error {
return errors.New("Threshold Scheme not supported")
}

// Verify the validity of a single signature fragment using the configured "threshold signature" scheme.
// Uses the keys stored in the CryptoConfig struct to verify the signature.
func (c *CryptoConfig) FragmentVerify(msg string, sig SigFragment) error {
if c.ThresholdScheme == "bls" {
if sig.Verify(msg, &c.ThresholdPublicMap) {
Expand Down
1 change: 0 additions & 1 deletion CTng/crypto/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ func TestSHA256(t *testing.T) {
}

func TestBLSFunctionality(T *testing.T) {
// Just
entities := []CTngID{
"a",
"b",
Expand Down
16 changes: 9 additions & 7 deletions CTng/crypto/generate_crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type CryptoStorage interface {
ReadCryptoConfig(file string) (*CryptoConfig, error)
}

// Generate a list of cryptoconfigs from a list of entity names.
// The threshold determines the k value in "k-of-n" threshold signing.
func GenerateEntityCryptoConfigs(entityIDs []CTngID, threshold int) ([]CryptoConfig, error) {
ThresholdScheme := "bls"
SignScheme := "rsa"
Expand Down Expand Up @@ -41,7 +43,7 @@ func GenerateEntityCryptoConfigs(entityIDs []CTngID, threshold int) ([]CryptoCon
}

//Generate configs without individual information
for i, _ := range configs {
for i := range configs {
configs[i] = CryptoConfig{
ThresholdScheme: ThresholdScheme,
SignScheme: SignScheme,
Expand All @@ -58,6 +60,8 @@ func GenerateEntityCryptoConfigs(entityIDs []CTngID, threshold int) ([]CryptoCon
return configs, nil
}

// Saves a list of cryptoconfigs to files in a directory.
// Each file is named the ID of the corresponding entity.
func SaveCryptoFiles(directory string, configs []CryptoConfig) error {
for _, config := range configs {
// fmt.Print(config)
Expand All @@ -70,6 +74,7 @@ func SaveCryptoFiles(directory string, configs []CryptoConfig) error {
return nil
}

// Read a storedcryptoconfig from a file, convert it to a cryptoconfig and return a pointer to it.
func ReadCryptoConfig(file string) (*CryptoConfig, error) {
scc := new(StoredCryptoConfig)
bytes, err := util.ReadByte(file)
Expand All @@ -81,6 +86,7 @@ func ReadCryptoConfig(file string) (*CryptoConfig, error) {
return cc, err
}

// Converts a CryptoConfig to a marshal-able format.
func NewStoredCryptoConfig(c *CryptoConfig) *StoredCryptoConfig {
scc := new(StoredCryptoConfig)
scc = &StoredCryptoConfig{
Expand All @@ -93,17 +99,13 @@ func NewStoredCryptoConfig(c *CryptoConfig) *StoredCryptoConfig {
SignaturePublicMap: c.SignaturePublicMap,
RSAPrivateKey: c.RSAPrivateKey,
}
// p, err := json.Marshal(c.RSAPrivateKey)
// if err != nil {
// panic(err)
// }
// scc.RSAPrivateKey = p
// scc.SignaturePublicMap = (&c.SignaturePublicMap).Serialize()
scc.ThresholdPublicMap = (&c.ThresholdPublicMap).Serialize()
scc.ThresholdSecretKey = (&c.ThresholdSecretKey).Serialize()
return scc
}

// Creates a cryptoconfig from a stored one. This is used for reading a stored file cryptoconfig.
// Returns a pointer to the new config.
func NewCryptoConfig(scc *StoredCryptoConfig) (*CryptoConfig, error) {
c := new(CryptoConfig)
c = &CryptoConfig{
Expand Down
1 change: 1 addition & 0 deletions CTng/crypto/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func GenerateMD5(data []byte) ([]byte, error) {
return hash, err
}

// Generates the SHA256 hash for the given bits.
func GenerateSHA256(data []byte) ([]byte, error) {
hash, _, err := generateHash(SHA256, data)
return hash, err
Expand Down
29 changes: 17 additions & 12 deletions CTng/crypto/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func (h HashAlgorithm) String() string {
}
}

// RSASig contains the ID of the signer and the rsa signature.
type RSASig struct {
Sig []byte
ID CTngID
Expand Down Expand Up @@ -122,14 +123,12 @@ func RSASigFromString(str string) (RSASig, error) {
// Follows the security assumption that "All public keys are known to all parties."
type RSAPublicMap map[CTngID]rsa.PublicKey

type BlsPrivateMap map[CTngID]bls.SecretKey

type BlsPublicMap map[CTngID]bls.PublicKey

// Serialization of these fields for transportation.
// Note that this is an inconvenience of this specific BLS library.
// Normally we would be able to just Marshal/Unmarshal.
// This could be an inconvenience of using the C implementation
// Normally, we would be able to just Marshal/Unmarshal a mapping.
// This is likely an inconvenience of using the C implementation of BLS.
func (p *BlsPublicMap) Serialize() map[string][]byte {
serialized := make(map[string][]byte)
for id, key := range *p {
Expand All @@ -138,6 +137,8 @@ func (p *BlsPublicMap) Serialize() map[string][]byte {
return serialized
}

// Deserialize takes the serialized version of the public map, deserializes it, and puts it in p.
// p should be allocated space for the BLSPublicMap to be stored.
func (p *BlsPublicMap) Deserialize(serialized map[string][]byte) error {
var err error
blsPub := new(bls.PublicKey)
Expand All @@ -151,6 +152,10 @@ func (p *BlsPublicMap) Deserialize(serialized map[string][]byte) error {
return nil
}

// This privatekey map is returned by the key generator. Individual private keys should be
// stored in the crypto configuration file of each entity.
type BlsPrivateMap map[CTngID]bls.SecretKey

// As of April 2022, the code is refactored so that storing blsIDs is no longer necessary.
// BLS ids are required for signing and verifying functions
// Thus, we give each Entity a BLS ID.
Expand Down Expand Up @@ -185,11 +190,14 @@ type SigFragment struct {
ID CTngID
}

// Convert a SigFragment to a string.
// Signatures need to be turned into strings to be stored in Gossip Objects.
// To convert back, use SigFragmentFromString().
func (s SigFragment) String() string {
return fmt.Sprintf(`{"sign":"%s","id":"%s"}`, s.Sign.SerializeToHexStr(), s.ID.String())
}

// Writes data into the signature fragment pointer.
// Returns a signature fragment generated from a string.
func SigFragmentFromString(str string) (SigFragment, error) {
s := new(SigFragment)
s.Sign = new(bls.Sign)
Expand Down Expand Up @@ -244,11 +252,7 @@ func ThresholdSigFromString(str string) (ThresholdSig, error) {
return *t, err
}

/*
2 options for the below: Package the cryptography information here, or
simply pass a "global config object" as the parameter
and let the individual functions parse it.
*/
//
type CryptoConfig struct {
Threshold int //f+1 is the threshold for signing
N int //n is the number of participants
Expand All @@ -263,8 +267,9 @@ type CryptoConfig struct {
ThresholdSecretKey bls.SecretKey // secret key for the current entity
}

// The below version is the serialized version of CryptoConfig.
// Again, this is because we're using the bls C implementation.
// This is the serialized version of CryptoConfig.
// Again, this is required because we're using the bls C implementation which can't be
// stored without serialization.
type StoredCryptoConfig struct {
SelfID CTngID // id of the current entity
Threshold int //f+1 is the threshold for signing
Expand Down

0 comments on commit ef15d9b

Please sign in to comment.