github.com/cloudflare/circl@v1.5.0/ot/simot/simotlocal.go (about)

     1  package simot
     2  
     3  import (
     4  	"crypto/aes"
     5  	"crypto/cipher"
     6  	"crypto/rand"
     7  	"crypto/subtle"
     8  	"errors"
     9  	"io"
    10  
    11  	"github.com/cloudflare/circl/group"
    12  	"golang.org/x/crypto/sha3"
    13  )
    14  
    15  const keyLength = 16
    16  
    17  // AES GCM encryption, we don't need to pad because our input is fixed length
    18  // Need to use authenticated encryption to defend against tampering on ciphertext
    19  // Input: key, plaintext message
    20  // Output: ciphertext
    21  func aesEncGCM(key, plaintext []byte) []byte {
    22  	block, err := aes.NewCipher(key)
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  
    27  	aesgcm, err := cipher.NewGCM(block)
    28  	if err != nil {
    29  		panic(err.Error())
    30  	}
    31  
    32  	nonce := make([]byte, aesgcm.NonceSize())
    33  	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
    34  		panic(err)
    35  	}
    36  
    37  	ciphertext := aesgcm.Seal(nonce, nonce, plaintext, nil)
    38  	return ciphertext
    39  }
    40  
    41  // AES GCM decryption
    42  // Input: key, ciphertext message
    43  // Output: plaintext
    44  func aesDecGCM(key, ciphertext []byte) ([]byte, error) {
    45  	block, err := aes.NewCipher(key)
    46  	if err != nil {
    47  		panic(err)
    48  	}
    49  	aesgcm, err := cipher.NewGCM(block)
    50  	if err != nil {
    51  		panic(err.Error())
    52  	}
    53  	nonceSize := aesgcm.NonceSize()
    54  	if len(ciphertext) < nonceSize {
    55  		return nil, errors.New("ciphertext too short")
    56  	}
    57  
    58  	nonce, encryptedMessage := ciphertext[:nonceSize], ciphertext[nonceSize:]
    59  
    60  	plaintext, err := aesgcm.Open(nil, nonce, encryptedMessage, nil)
    61  
    62  	return plaintext, err
    63  }
    64  
    65  // Initialization
    66  
    67  // Input: myGroup, the group we operate in
    68  // Input: m0, m1 the 2 message of the sender
    69  // Input: index, the index of this SimOT
    70  // Output: A = [a]G, a the sender randomness
    71  func (sender *Sender) InitSender(myGroup group.Group, m0, m1 []byte, index int) group.Element {
    72  	sender.a = myGroup.RandomNonZeroScalar(rand.Reader)
    73  	sender.k0 = make([]byte, keyLength)
    74  	sender.k1 = make([]byte, keyLength)
    75  	sender.m0 = m0
    76  	sender.m1 = m1
    77  	sender.index = index
    78  	sender.A = myGroup.NewElement()
    79  	sender.A.MulGen(sender.a)
    80  	sender.myGroup = myGroup
    81  	return sender.A.Copy()
    82  }
    83  
    84  // Round 1
    85  
    86  // ---- sender should send A to receiver ----
    87  
    88  // Input: myGroup, the group we operate in
    89  // Input: choice, the receiver choice bit
    90  // Input: index, the index of this SimOT
    91  // Input: A, from sender
    92  // Output: B = [b]G if c == 0, B = A+[b]G if c == 1 (Implementation in constant time). b, the receiver randomness
    93  func (receiver *Receiver) Round1Receiver(myGroup group.Group, choice int, index int, A group.Element) group.Element {
    94  	receiver.b = myGroup.RandomNonZeroScalar(rand.Reader)
    95  	receiver.c = choice
    96  	receiver.kR = make([]byte, keyLength)
    97  	receiver.index = index
    98  	receiver.A = A
    99  	receiver.myGroup = myGroup
   100  
   101  	bG := myGroup.NewElement()
   102  	bG.MulGen(receiver.b)
   103  	AorI := myGroup.NewElement()
   104  	AorI.CMov(choice, A)
   105  	receiver.B = myGroup.NewElement()
   106  	receiver.B.Add(bG, AorI)
   107  
   108  	return receiver.B.Copy()
   109  }
   110  
   111  // Round 2
   112  
   113  // ---- receiver should send B to sender ----
   114  
   115  // Input: B from the receiver
   116  // Output: e0, e1, encryption of m0 and m1 under key k0, k1
   117  func (sender *Sender) Round2Sender(B group.Element) ([]byte, []byte) {
   118  	sender.B = B
   119  
   120  	aB := sender.myGroup.NewElement()
   121  	aB.Mul(sender.B, sender.a)
   122  	maA := sender.myGroup.NewElement()
   123  	maA.Mul(sender.A, sender.a)
   124  	maA.Neg(maA)
   125  	aBaA := sender.myGroup.NewElement()
   126  	aBaA.Add(aB, maA)
   127  
   128  	// Hash the whole transcript A|B|...
   129  	AByte, errByte := sender.A.MarshalBinary()
   130  	if errByte != nil {
   131  		panic(errByte)
   132  	}
   133  	BByte, errByte := sender.B.MarshalBinary()
   134  	if errByte != nil {
   135  		panic(errByte)
   136  	}
   137  	aBByte, errByte := aB.MarshalBinary()
   138  	if errByte != nil {
   139  		panic(errByte)
   140  	}
   141  	hashByte0 := append(AByte, BByte...)
   142  	hashByte0 = append(hashByte0, aBByte...)
   143  
   144  	s := sha3.NewShake128()
   145  	_, errWrite := s.Write(hashByte0)
   146  	if errWrite != nil {
   147  		panic(errWrite)
   148  	}
   149  	_, errRead := s.Read(sender.k0)
   150  	if errRead != nil {
   151  		panic(errRead)
   152  	}
   153  
   154  	aBaAByte, errByte := aBaA.MarshalBinary()
   155  	if errByte != nil {
   156  		panic(errByte)
   157  	}
   158  	hashByte1 := append(AByte, BByte...)
   159  	hashByte1 = append(hashByte1, aBaAByte...)
   160  	s = sha3.NewShake128()
   161  	_, errWrite = s.Write(hashByte1)
   162  	if errWrite != nil {
   163  		panic(errWrite)
   164  	}
   165  	_, errRead = s.Read(sender.k1)
   166  	if errRead != nil {
   167  		panic(errRead)
   168  	}
   169  
   170  	e0 := aesEncGCM(sender.k0, sender.m0)
   171  	sender.e0 = e0
   172  
   173  	e1 := aesEncGCM(sender.k1, sender.m1)
   174  	sender.e1 = e1
   175  
   176  	return sender.e0, sender.e1
   177  }
   178  
   179  // Round 3
   180  
   181  // ---- sender should send e0, e1 to receiver ----
   182  
   183  // Input: e0, e1: encryption of m0 and m1 from the sender
   184  // Input: choice, choice bit of receiver
   185  // Choose e0 or e1 based on choice bit in constant time
   186  func (receiver *Receiver) Round3Receiver(e0, e1 []byte, choice int) error {
   187  	receiver.ec = make([]byte, len(e1))
   188  	// If c == 1, copy e1
   189  	subtle.ConstantTimeCopy(choice, receiver.ec, e1)
   190  	// If c == 0, copy e0
   191  	subtle.ConstantTimeCopy(1-choice, receiver.ec, e0)
   192  
   193  	AByte, errByte := receiver.A.MarshalBinary()
   194  	if errByte != nil {
   195  		panic(errByte)
   196  	}
   197  	BByte, errByte := receiver.B.MarshalBinary()
   198  	if errByte != nil {
   199  		panic(errByte)
   200  	}
   201  	bA := receiver.myGroup.NewElement()
   202  	bA.Mul(receiver.A, receiver.b)
   203  	bAByte, errByte := bA.MarshalBinary()
   204  	if errByte != nil {
   205  		panic(errByte)
   206  	}
   207  	// Hash the whole transcript so far
   208  	hashByte := append(AByte, BByte...)
   209  	hashByte = append(hashByte, bAByte...)
   210  
   211  	s := sha3.NewShake128()
   212  	_, errWrite := s.Write(hashByte)
   213  	if errWrite != nil {
   214  		panic(errWrite)
   215  	}
   216  	_, errRead := s.Read(receiver.kR) // kR, decryption key of mc
   217  	if errRead != nil {
   218  		panic(errRead)
   219  	}
   220  	mc, errDec := aesDecGCM(receiver.kR, receiver.ec)
   221  	if errDec != nil {
   222  		return errDec
   223  	}
   224  	receiver.mc = mc
   225  	return nil
   226  }
   227  
   228  func (receiver *Receiver) Returnmc() []byte {
   229  	return receiver.mc
   230  }
   231  
   232  func (sender *Sender) Returne0e1() ([]byte, []byte) {
   233  	return sender.e0, sender.e1
   234  }
   235  
   236  func (sender *Sender) Returnm0m1() ([]byte, []byte) {
   237  	return sender.m0, sender.m1
   238  }