newhope_simple.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // newhope_simple.go - NewHope-Simple interface.
  2. //
  3. // To the extent possible under law, Yawning Angel has waived all copyright
  4. // and related or neighboring rights to newhope, using the Creative
  5. // Commons "CC0" public domain dedication. See LICENSE or
  6. // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
  7. package newhope
  8. import (
  9. "io"
  10. "golang.org/x/crypto/sha3"
  11. )
  12. const (
  13. // HighBytes is the length of the encoded secret in bytes.
  14. HighBytes = 384
  15. // SendASimpleSize is the length of Alice's NewHope-Simple public key in
  16. // bytes.
  17. SendASimpleSize = PolyBytes + SeedBytes
  18. // SendBSimpleSize is the length of Bob's NewHope-Simple public key in
  19. // bytes.
  20. SendBSimpleSize = PolyBytes + HighBytes
  21. )
  22. func encodeBSimple(r []byte, b *poly, v *poly) {
  23. b.toBytes(r)
  24. v.compress(r[PolyBytes:])
  25. }
  26. func decodeBSimple(b *poly, v *poly, r []byte) {
  27. b.fromBytes(r)
  28. v.decompress(r[PolyBytes:])
  29. }
  30. // PublicKeySimpleAlice is Alice's NewHope-Simple public key.
  31. type PublicKeySimpleAlice struct {
  32. Send [SendASimpleSize]byte
  33. }
  34. // PrivateKeySimpleAlice is Alice's NewHope-Simple private key.
  35. type PrivateKeySimpleAlice struct {
  36. sk poly
  37. }
  38. // Reset clears all sensitive information such that it no longer appears in
  39. // memory.
  40. func (k *PrivateKeySimpleAlice) Reset() {
  41. k.sk.reset()
  42. }
  43. // GenerateKeyPairSimpleAlice returns a NewHope-Simple private/public key pair.
  44. // The private key is generated using the given reader, which must return
  45. // random data. The receiver side of the key exchange (aka "Bob") MUST use
  46. // KeyExchangeSimpleBob() instead of this routine.
  47. func GenerateKeyPairSimpleAlice(rand io.Reader) (*PrivateKeySimpleAlice, *PublicKeySimpleAlice, error) {
  48. var a, e, pk, r poly
  49. var seed, noiseSeed [SeedBytes]byte
  50. if _, err := io.ReadFull(rand, seed[:]); err != nil {
  51. return nil, nil, err
  52. }
  53. seed = sha3.Sum256(seed[:]) // Don't send output of system RNG.
  54. a.uniform(&seed, TorSampling)
  55. if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
  56. return nil, nil, err
  57. }
  58. defer memwipe(noiseSeed[:])
  59. privKey := new(PrivateKeySimpleAlice)
  60. privKey.sk.getNoise(&noiseSeed, 0)
  61. privKey.sk.ntt()
  62. e.getNoise(&noiseSeed, 1)
  63. e.ntt()
  64. pubKey := new(PublicKeySimpleAlice)
  65. r.pointwise(&privKey.sk, &a)
  66. pk.add(&e, &r)
  67. encodeA(pubKey.Send[:], &pk, &seed)
  68. return privKey, pubKey, nil
  69. }
  70. // PublicKeySimpleBob is Bob's NewHope-Simple public key.
  71. type PublicKeySimpleBob struct {
  72. Send [SendBSimpleSize]byte
  73. }
  74. // KeyExchangeSimpleBob is the Responder side of the NewHope-Simple key
  75. // exchange. The shared secret and "public key" are generated using the
  76. // given reader, which must return random data.
  77. func KeyExchangeSimpleBob(rand io.Reader, alicePk *PublicKeySimpleAlice) (*PublicKeySimpleBob, []byte, error) {
  78. var pka, a, sp, ep, bp, v, epp, m poly
  79. var seed, noiseSeed [SeedBytes]byte
  80. if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
  81. return nil, nil, err
  82. }
  83. defer memwipe(noiseSeed[:])
  84. var sharedKey [SharedSecretSize]byte
  85. if _, err := io.ReadFull(rand, sharedKey[:]); err != nil {
  86. return nil, nil, err
  87. }
  88. defer memwipe(sharedKey[:])
  89. sharedKey = sha3.Sum256(sharedKey[:])
  90. m.fromMsg(sharedKey[:])
  91. decodeA(&pka, &seed, alicePk.Send[:])
  92. a.uniform(&seed, TorSampling)
  93. sp.getNoise(&noiseSeed, 0)
  94. sp.ntt()
  95. ep.getNoise(&noiseSeed, 1)
  96. ep.ntt()
  97. bp.pointwise(&a, &sp)
  98. bp.add(&bp, &ep)
  99. v.pointwise(&pka, &sp)
  100. v.invNtt()
  101. epp.getNoise(&noiseSeed, 2)
  102. v.add(&v, &epp)
  103. v.add(&v, &m) // add key
  104. pubKey := new(PublicKeySimpleBob)
  105. encodeBSimple(pubKey.Send[:], &bp, &v)
  106. mu := sha3.Sum256(sharedKey[:])
  107. // Scrub the sensitive stuff...
  108. sp.reset()
  109. v.reset()
  110. m.reset()
  111. return pubKey, mu[:], nil
  112. }
  113. // KeyExchangeSimpleAlice is the Initiaitor side of the NewHope-Simple key
  114. // exchange. The provided private key is obliterated prior to returning.
  115. func KeyExchangeSimpleAlice(bobPk *PublicKeySimpleBob, aliceSk *PrivateKeySimpleAlice) ([]byte, error) {
  116. var v, bp, k poly
  117. decodeBSimple(&bp, &v, bobPk.Send[:])
  118. k.pointwise(&aliceSk.sk, &bp)
  119. k.invNtt()
  120. k.sub(&k, &v)
  121. var sharedKey [SharedSecretSize]byte
  122. k.toMsg(sharedKey[:])
  123. // mu <- Sha3-256(v')
  124. mu := sha3.Sum256(sharedKey[:])
  125. // Scrub the sensitive stuff...
  126. memwipe(sharedKey[:])
  127. k.reset()
  128. aliceSk.Reset()
  129. return mu[:], nil
  130. }