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)