poly_simple.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // poly_simple.go - NewHope-Simple polynomial.
  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. func coeffFreeze(x uint16) uint16 {
  9. var c int16
  10. r := barrettReduce(x)
  11. m := r - paramQ
  12. c = int16(m)
  13. c >>= 15
  14. r = m ^ ((r ^ m) & uint16(c))
  15. return r
  16. }
  17. // Computes abs(x-Q/2)
  18. func flipAbs(x uint16) uint16 {
  19. r := int16(coeffFreeze(x))
  20. r = r - paramQ/2
  21. m := r >> 15
  22. return uint16((r + m) ^ m)
  23. }
  24. func (p *poly) compress(r []byte) {
  25. var t [8]uint32
  26. for i, k := 0, 0; i < paramN; i, k = i+8, k+3 {
  27. for j := range t {
  28. t[j] = uint32(coeffFreeze(p.coeffs[i+j]))
  29. t[j] = (((t[j] << 3) + paramQ/2) / paramQ) & 0x7
  30. }
  31. r[k] = byte(t[0]) | byte(t[1]<<3) | byte(t[2]<<6)
  32. r[k+1] = byte(t[2]>>2) | byte(t[3]<<1) | byte(t[4]<<4) | byte(t[5]<<7)
  33. r[k+2] = byte(t[5]>>1) | byte(t[6]<<2) | byte(t[7]<<5)
  34. }
  35. for i := range t {
  36. t[i] = 0
  37. }
  38. }
  39. func (p *poly) decompress(a []byte) {
  40. for i := 0; i < paramN; i += 8 {
  41. a0, a1, a2 := uint16(a[0]), uint16(a[1]), uint16(a[2])
  42. p.coeffs[i+0] = a0 & 7
  43. p.coeffs[i+1] = (a0 >> 3) & 7
  44. p.coeffs[i+2] = (a0 >> 6) | ((a1 << 2) & 4)
  45. p.coeffs[i+3] = (a1 >> 1) & 7
  46. p.coeffs[i+4] = (a1 >> 4) & 7
  47. p.coeffs[i+5] = (a1 >> 7) | ((a2 << 1) & 6)
  48. p.coeffs[i+6] = (a2 >> 2) & 7
  49. p.coeffs[i+7] = (a2 >> 5)
  50. a = a[3:]
  51. for j := 0; j < 8; j++ {
  52. p.coeffs[i+j] = uint16((uint32(p.coeffs[i+j])*paramQ + 4) >> 3)
  53. }
  54. }
  55. }
  56. func (p *poly) fromMsg(msg []byte) {
  57. for i := uint(0); i < 32; i++ { // XXX: const for 32
  58. for j := uint(0); j < 8; j++ {
  59. mask := -(uint16((msg[i] >> j) & 1))
  60. p.coeffs[8*i+j+0] = mask & (paramQ / 2)
  61. p.coeffs[8*i+j+256] = mask & (paramQ / 2)
  62. p.coeffs[8*i+j+512] = mask & (paramQ / 2)
  63. p.coeffs[8*i+j+768] = mask & (paramQ / 2)
  64. }
  65. }
  66. }
  67. func (p *poly) toMsg(msg []byte) {
  68. memwipe(msg[0:32])
  69. for i := uint(0); i < 256; i++ {
  70. t := flipAbs(p.coeffs[i+0])
  71. t += flipAbs(p.coeffs[i+256])
  72. t += flipAbs(p.coeffs[i+512])
  73. t += flipAbs(p.coeffs[i+768])
  74. //t = (~(t - PARAM_Q));
  75. t = (t - paramQ)
  76. t >>= 15
  77. msg[i>>3] |= byte(t << (i & 7))
  78. }
  79. }
  80. func (p *poly) sub(a, b *poly) {
  81. for i := range p.coeffs {
  82. p.coeffs[i] = barrettReduce(a.coeffs[i] + 3*paramQ - b.coeffs[i])
  83. }
  84. }