github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bcns/ringlwe.go (about)

     1  //
     2  // Ring Learning With Errors (Interface)
     3  //
     4  // To the extent possible under law, Yawning Angel waived all copyright
     5  // and related or neighboring rights to bcns, using the Creative
     6  // Commons "CC0" public domain dedication. See LICENSE or
     7  // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
     8  
     9  // Package bcns implements a key exchange based on the Ring Learning With
    10  // Errors Problem.  It is based heavily on the Public Domain implementation
    11  // by Joppe W. Bos, Craig Costello, Michael Naehrig, and Douglas Stebila.
    12  //
    13  // For more information see: http://eprint.iacr.org/2014/599
    14  //
    15  package bcns
    16  
    17  import (
    18  	"crypto"
    19  	"encoding/binary"
    20  	"errors"
    21  	"io"
    22  )
    23  
    24  const (
    25  	// PublicKeySize is the length of a Ring-LWE public key in bytes.
    26  	PublicKeySize = 4096
    27  
    28  	// PrivateKeySize is the length of a Ring-LWE private key in bytes.
    29  	PrivateKeySize = 4096
    30  
    31  	// RecDataSize is the length of the reconcilliation data in bytes.
    32  	RecDataSize = 128
    33  
    34  	// SharedSecretSize is the length of a Ring-LWE Shared Secret in bytes.
    35  	SharedSecretSize = 128
    36  )
    37  
    38  var (
    39  	// ErrInvalidPublicKeySize is the error returned when a public key blob
    40  	// is an invalid length.
    41  	ErrInvalidPublicKeySize = errors.New("rlwe: invalid public key length")
    42  
    43  	// ErrInvalidRecDataSize is the error returned when a reconcilliation
    44  	// data blob is an invalid length.
    45  	ErrInvalidRecDataSize = errors.New("rlwe: invalid reconcilliation data length")
    46  )
    47  
    48  // PublicKey is a Ring-LWE public key.
    49  type PublicKey struct {
    50  	publicKey [1024]uint32
    51  }
    52  
    53  // FromBytes deserializes a Ring-LWE public key.
    54  func (pub *PublicKey) FromBytes(b []byte) error {
    55  	if len(b) != PublicKeySize {
    56  		return ErrInvalidPublicKeySize
    57  	}
    58  	for i := range pub.publicKey {
    59  		pub.publicKey[i] = binary.LittleEndian.Uint32(b[i*4:])
    60  	}
    61  	return nil
    62  }
    63  
    64  // Bytes serializes a Ring-LWE public key.
    65  func (pub *PublicKey) Bytes() []byte {
    66  	ret := make([]byte, PublicKeySize)
    67  	for i, v := range pub.publicKey {
    68  		binary.LittleEndian.PutUint32(ret[i*4:], v)
    69  	}
    70  	return ret
    71  }
    72  
    73  // PrivateKey is a Ring-LWE private key.
    74  type PrivateKey struct {
    75  	privateKey [1024]uint32
    76  }
    77  
    78  // FromBytes deserializes a Ring-LWE public key.
    79  func (priv *PrivateKey) FromBytes(b []byte) error {
    80  	if len(b) != PrivateKeySize {
    81  		return ErrInvalidPublicKeySize
    82  	}
    83  	for i := range priv.privateKey {
    84  		priv.privateKey[i] = binary.LittleEndian.Uint32(b[i*4:])
    85  	}
    86  	return nil
    87  }
    88  
    89  // Bytes serializes a Ring-LWE public key.
    90  func (priv *PrivateKey) Bytes() []byte {
    91  	ret := make([]byte, PrivateKeySize)
    92  	for i, v := range priv.privateKey {
    93  		binary.LittleEndian.PutUint32(ret[i*4:], v)
    94  	}
    95  	return ret
    96  }
    97  
    98  
    99  // RecData is the Ring-LWE reconcilliation data.
   100  type RecData struct {
   101  	recData [16]uint64
   102  }
   103  
   104  // FromBytes deserializes a Ring-LWE reconcilliation data blob.
   105  func (rec *RecData) FromBytes(b []byte) error {
   106  	if len(b) != RecDataSize {
   107  		return ErrInvalidRecDataSize
   108  	}
   109  	for i := range rec.recData {
   110  		rec.recData[i] = binary.LittleEndian.Uint64(b[i*8:])
   111  	}
   112  	return nil
   113  }
   114  
   115  // Bytes serializes Ring-LWE reconcilliation data.
   116  func (rec *RecData) Bytes() []byte {
   117  	ret := make([]byte, RecDataSize)
   118  	for i, v := range rec.recData {
   119  		binary.LittleEndian.PutUint64(ret[i*8:], v)
   120  	}
   121  	return ret
   122  }
   123  
   124  // GenerateKeyPair returns a private/public key pair.  The private key is
   125  // generated using the given reader which must return random data.
   126  func GenerateKeyPair(r io.Reader) (*PrivateKey, *PublicKey, error) {
   127  	pub := new(PublicKey)
   128  	priv := new(PrivateKey)
   129  	err := kexGenerateKeypair(r, &rlweARef, &priv.privateKey, &pub.publicKey)
   130  	if err != nil {
   131  		return nil, nil, err
   132  	}
   133  	return priv, pub, nil
   134  }
   135  
   136  // KeyExchangeAlice is the Initiator side of the Ring-LWE key exchange.
   137  func KeyExchangeAlice(bobPk *PublicKey, aliceSk *PrivateKey, rec *RecData) []byte {
   138  	var ss [16]uint64
   139  	kexComputeKeyAlice(&bobPk.publicKey, &aliceSk.privateKey, &rec.recData, &ss)
   140  	out := make([]byte, SharedSecretSize)
   141  	for i := range ss {
   142  		binary.LittleEndian.PutUint64(out[i*8:], ss[i])
   143  		ss[i] = 0
   144  	}
   145  	return out
   146  }
   147  
   148  // KeyExchangeBob is the Responder side of the Ring-LWE key exchange.  The
   149  // reconciliation data and shared secret are generated using the given reader
   150  // which must return random data.
   151  func KeyExchangeBob(r io.Reader, alicePk *PublicKey, bobSk *PrivateKey) (*RecData, []byte, error) {
   152  	var ss [16]uint64
   153  	rec := new(RecData)
   154  	err := kexComputeKeyBob(r, &alicePk.publicKey, &bobSk.privateKey, &rec.recData, &ss)
   155  	if err != nil {
   156  		return nil, nil, err
   157  	}
   158  	out := make([]byte, SharedSecretSize)
   159  	for i := range ss {
   160  		binary.LittleEndian.PutUint64(out[i*8:], ss[i])
   161  		ss[i] = 0
   162  	}
   163  	return rec, out, nil
   164  }
   165  
   166  var _ crypto.PublicKey = (*PublicKey)(nil)
   167  var _ crypto.PrivateKey = (*PrivateKey)(nil)