jlxip

RFC 7748 errata

Feb 27th, 2024
1,463
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.05 KB | None | 0 0
  1. # Regarding, RFC 7748, Section 5.2, X448, second vector, the given input
  2. # u-coordinate is not part of a valid point on the Montgomery form of Curve448.
  3. # I suggest replacing the point with a valid one: (2^447 + 100)*G
  4. # Execute at: https://sagecell.sagemath.org/
  5.  
  6.  
  7. # Curve448 parameters, as per RFC 7748, Section 4.2
  8. # Galois Field
  9. F = GF(2^448 - 2^224 - 1)
  10. # Montgomery form parameters
  11. A = 156326
  12. B = 1
  13.  
  14.  
  15.  
  16. # --- AUXILIARY FUNCTIONS ---
  17. def is_valid_point(u):
  18.     # Check if the point satisfies the curve equation v^2 = u^3 + Au^2 + u in the field F
  19.     u3_plus_Au2_plus_u = u^3 + A*u^2 + u
  20.     # Check if this is a quadratic residue in F, meaning there exists a v^2
  21.     return u3_plus_Au2_plus_u.is_square()
  22. rawslicer = lambda x, k : [x[k*i:k*(i+1)] for i in range(len(x)//k)]
  23. stringslicer = lambda x, k : ''.join(rawslicer(x, k))
  24. little2big = lambda x : stringslicer(x, 2)
  25. def little(x):
  26.     if len(x) % 2: x = '0' + x
  27.     return ''.join(rawslicer(x, 2)[::-1])
  28. def fixscalar(d):
  29.     d >>= 2
  30.     d <<= 2
  31.     d |= 1 << 447
  32.     return d
  33.  
  34.  
  35.  
  36. # Generator's u-coordinate
  37. G = F(5)
  38. # First test vector, from Section 5.2, X448
  39. FIRST = F(382239910814107330116229961234899377031416365240571325148346555922438025162094455820962429142971339584360034337310079791515452463053830)
  40. FIRSTSCALAR = F(fixscalar(599189175373896402783756016145213256157230856085026129926891459468622403380588640249457727683869421921443004045221642549886377526240828))
  41. FIRSTOUTPUT = 'ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f'
  42. FIRSTOUTPUT = int.from_bytes(bytes.fromhex(FIRSTOUTPUT), byteorder='little')
  43. # Second test vector
  44. SECOND = F(622761797758325444462922068431234180649590390024811299761625153767228042600197997696167956134770744996690267634159427999832340166786063)
  45. SECONDSCALAR = F(fixscalar(633254335906970592779259481534862372382525155252028961056404001332122152890562527156973881968934311400345568203929409663925541994577184))
  46.  
  47. # Prove my point
  48. assert is_valid_point(G)
  49. assert is_valid_point(FIRST)
  50. assert not is_valid_point(SECOND)
  51.  
  52. # Curve implementation
  53. ec = EllipticCurve(F, [0,A,0,B,0])
  54. assert (FIRSTSCALAR * ec.lift_x(FIRST))[0] == FIRSTOUTPUT
  55.  
  56. # Proposed point
  57. PROPOSED = fixscalar(100) * ec.lift_x(G)
  58. PROPOSED = PROPOSED[0] # Get only u
  59. assert is_valid_point(PROPOSED)
  60.  
  61. # Proposed output, keeping the same d
  62. out = SECONDSCALAR * ec.lift_x(PROPOSED)
  63. out = out[0] # Only u
  64.  
  65. # Encodings
  66. stru = str(PROPOSED)
  67. hexu = little(hex(PROPOSED)[2:])
  68. hexout = little(hex(out)[2:])
  69.  
  70. # Just in case
  71. assert (SECONDSCALAR * ec.lift_x(PROPOSED))[0] == out
  72. assert int.from_bytes(bytes.fromhex(hexu), byteorder='little') == PROPOSED
  73. assert int.from_bytes(bytes.fromhex(hexout), byteorder='little') == out
  74.  
  75. print('   Input u-coordinate:')
  76. print('     '+'\n     '.join(rawslicer(hexu, len(hexu)//2)))
  77. print('   Input u-coordinate as a number (base 10):')
  78. print('     '+'\n     '.join(rawslicer(stru, len(stru)//3)))
  79. print('   Output u-coordinate:')
  80. print('     '+'\n     '.join(rawslicer(hexout, len(hexout)//2)))
  81.  
Advertisement
Add Comment
Please, Sign In to add comment