github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/repository/keystore.go (about)

     1  package repository
     2  
     3  import (
     4  	"crypto/rand"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/hoffie/larasync/helpers/crypto"
     9  	edhelpers "github.com/hoffie/larasync/helpers/ed25519"
    10  	"github.com/hoffie/larasync/repository/content"
    11  )
    12  
    13  const (
    14  	// Key Sizes
    15  
    16  	// PrivateKeySize is the keySize which is used for signatures in the
    17  	// system.
    18  	PrivateKeySize = crypto.PrivateKeySize
    19  	// PublicKeySize is the keySize for public signature keys.
    20  	PublicKeySize = crypto.PublicKeySize
    21  	// EncryptionKeySize represents the size of the key used for
    22  	// encrypting.
    23  	EncryptionKeySize = crypto.EncryptionKeySize
    24  	// HashingKeySize represents the size of the key used for
    25  	// generating content hashes (HMAC).
    26  	HashingKeySize = crypto.HashingKeySize
    27  
    28  	// ids for our keys in the storage
    29  	encryptionKeyName     = "encryption.key"
    30  	hashingKeyName        = "hashing.key"
    31  	signingPrivateKeyName = "signing.priv"
    32  	signingPublicKeyName  = "signing.pub"
    33  )
    34  
    35  // KeyStore is responsible for loading keys from the storage backend.
    36  type KeyStore struct {
    37  	base    string
    38  	storage *content.ByteStorage
    39  }
    40  
    41  // NewKeyStore returns a new KeyStore instance.
    42  func NewKeyStore(storage content.Storage) *KeyStore {
    43  	ks := &KeyStore{storage: content.NewByteStorage(storage)}
    44  	return ks
    45  }
    46  
    47  // SetEncryptionKey sets the encryption key
    48  func (ks *KeyStore) SetEncryptionKey(key [EncryptionKeySize]byte) error {
    49  	return ks.storage.SetBytes(encryptionKeyName, key[:])
    50  }
    51  
    52  // EncryptionKey returns the encryption key.
    53  func (ks *KeyStore) EncryptionKey() ([EncryptionKeySize]byte, error) {
    54  	key, err := ks.storage.GetBytes(encryptionKeyName)
    55  	if len(key) != EncryptionKeySize {
    56  		return [EncryptionKeySize]byte{}, fmt.Errorf(
    57  			"invalid key length (%d)", len(key))
    58  	}
    59  	var arrKey [EncryptionKeySize]byte
    60  	copy(arrKey[:], key)
    61  	return arrKey, err
    62  }
    63  
    64  // SetSigningPrivateKey sets the signing private key
    65  func (ks *KeyStore) SetSigningPrivateKey(key [PrivateKeySize]byte) error {
    66  	return ks.storage.SetBytes(signingPrivateKeyName, key[:])
    67  }
    68  
    69  // SigningPrivateKey returns the signing private key.
    70  func (ks *KeyStore) SigningPrivateKey() ([PrivateKeySize]byte, error) {
    71  	key, err := ks.storage.GetBytes(signingPrivateKeyName)
    72  	if len(key) != PrivateKeySize {
    73  		return [PrivateKeySize]byte{}, fmt.Errorf(
    74  			"invalid key length (%d)", len(key))
    75  	}
    76  	var arrKey [PrivateKeySize]byte
    77  	copy(arrKey[:], key)
    78  	return arrKey, err
    79  }
    80  
    81  // SetSigningPublicKey sets the signing key's public key.
    82  func (ks *KeyStore) SetSigningPublicKey(key []byte) error {
    83  	return ks.storage.SetBytes(signingPublicKeyName, key)
    84  }
    85  
    86  // SigningPublicKey returns the signing public key.
    87  func (ks *KeyStore) SigningPublicKey() ([PublicKeySize]byte, error) {
    88  	privKey, err := ks.SigningPrivateKey()
    89  	if err != nil {
    90  		return ks.signingPublicKeyFromStorage()
    91  	}
    92  	return edhelpers.GetPublicKeyFromPrivate(privKey), nil
    93  }
    94  
    95  // signingPubkeyFromStorage returns the repository signing public key.
    96  //
    97  // It tries to retrieve the stored copy and is only called if the public key
    98  // cannot be derived from the private key (i.e. if the private key is not
    99  // available in this repository).
   100  func (ks *KeyStore) signingPublicKeyFromStorage() ([PublicKeySize]byte, error) {
   101  	key, err := ks.storage.GetBytes(signingPublicKeyName)
   102  	if len(key) != PublicKeySize {
   103  		return [PublicKeySize]byte{}, fmt.Errorf(
   104  			"invalid key length (%d)", len(key))
   105  	}
   106  	var arrKey [PublicKeySize]byte
   107  	copy(arrKey[:], key)
   108  	return arrKey, err
   109  }
   110  
   111  // SetHashingKey sets the repository hashing key (content addressing)
   112  func (ks *KeyStore) SetHashingKey(key [HashingKeySize]byte) error {
   113  	return ks.storage.SetBytes(hashingKeyName, key[:])
   114  }
   115  
   116  // HashingKey returns the repository signing private key.
   117  func (ks *KeyStore) HashingKey() ([HashingKeySize]byte, error) {
   118  	key, err := ks.storage.GetBytes(hashingKeyName)
   119  	if len(key) != HashingKeySize {
   120  		return [HashingKeySize]byte{}, fmt.Errorf(
   121  			"invalid key length (%d)", len(key))
   122  	}
   123  	var arrKey [HashingKeySize]byte
   124  	copy(arrKey[:], key)
   125  	return arrKey, err
   126  }
   127  
   128  // CreateEncryptionKey generates a random encryption key.
   129  func (ks *KeyStore) CreateEncryptionKey() error {
   130  	key := make([]byte, EncryptionKeySize)
   131  	_, err := rand.Read(key)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	err = ks.storage.SetBytes(encryptionKeyName, key)
   136  	return err
   137  }
   138  
   139  // CreateSigningKey generates a random signing key.
   140  func (ks *KeyStore) CreateSigningKey() error {
   141  	_, privKey, err := edhelpers.GenerateKey()
   142  	if err != nil {
   143  		return err
   144  	}
   145  	if privKey == nil {
   146  		return errors.New("no private key generated")
   147  	}
   148  	err = ks.SetSigningPrivateKey(*privKey)
   149  	return err
   150  }
   151  
   152  // CreateHashingKey generates a random hashing key.
   153  func (ks *KeyStore) CreateHashingKey() error {
   154  	key := make([]byte, HashingKeySize)
   155  	var arrKey [HashingKeySize]byte
   156  	_, err := rand.Read(key)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	copy(arrKey[:], key)
   161  	err = ks.SetHashingKey(arrKey)
   162  	return err
   163  }