Module: JOSE::JWA::Ed448
Constant Summary collapse
- C_bits =
456- C_bytes =
(C_bits + 7) / 8
- C_secretbytes =
C_bytes- C_legacysecretbytes =
32- C_publickeybytes =
C_bytes- C_secretkeybytes =
C_secretbytes + C_publickeybytes
- C_legacysecretkeybytes =
C_legacysecretbytes + C_publickeybytes
- C_signaturebytes =
C_bytes + C_bytes
- C_B =
JOSE::JWA::Edwards448Point.stdbase.freeze
Instance Method Summary collapse
- #keypair(secret = nil) ⇒ Object
- #pk_to_curve448(pk) ⇒ Object
- #secret_to_curve448(secret) ⇒ Object
- #secret_to_pk(secret) ⇒ Object
- #sign(m, sk, ctx = nil) ⇒ Object
- #sign_ph(m, sk, ctx = nil) ⇒ Object
- #sk_to_curve448(sk) ⇒ Object
- #sk_to_pk(sk) ⇒ Object
- #sk_to_secret(sk) ⇒ Object
- #verify(sig, m, pk, ctx = nil) ⇒ Object
- #verify_ph(sig, m, pk, ctx = nil) ⇒ Object
Instance Method Details
#keypair(secret = nil) ⇒ Object
28 29 30 31 32 33 |
# File 'lib/jose/jwa/ed448.rb', line 28 def keypair(secret = nil) secret ||= SecureRandom.random_bytes(C_secretbytes) pk = secret_to_pk(secret) sk = secret + pk return pk, sk end |
#pk_to_curve448(pk) ⇒ Object
51 52 53 54 55 56 |
# File 'lib/jose/jwa/ed448.rb', line 51 def pk_to_curve448(pk) raise ArgumentError, "pk must be #{C_publickeybytes} bytes" if pk.bytesize != C_publickeybytes a = C_B.decode(pk) u = a.y.sqr / a.x.sqr return u.to_bytes(448) end |
#secret_to_curve448(secret) ⇒ Object
15 16 17 18 19 20 21 |
# File 'lib/jose/jwa/ed448.rb', line 15 def secret_to_curve448(secret) raise ArgumentError, "secret must be #{C_secretbytes} bytes" if secret.bytesize != C_secretbytes and secret.bytesize != C_legacysecretbytes curve448_scalar = JOSE::JWA::SHA3.shake256(secret, 114)[0, 56] curve448_scalar.setbyte(0, curve448_scalar.getbyte(0) & 252) curve448_scalar.setbyte(55, curve448_scalar.getbyte(55) | 128) return curve448_scalar end |
#secret_to_pk(secret) ⇒ Object
23 24 25 26 |
# File 'lib/jose/jwa/ed448.rb', line 23 def secret_to_pk(secret) raise ArgumentError, "secret must be #{C_secretbytes} bytes" if secret.bytesize != C_secretbytes and secret.bytesize != C_legacysecretbytes return (C_B * OpenSSL::BN.new(secret_to_curve448(secret).reverse, 2).to_i).encode() end |
#sign(m, sk, ctx = nil) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/jose/jwa/ed448.rb', line 58 def sign(m, sk, ctx = nil) raise ArgumentError, "sk must be #{C_secretkeybytes} bytes" if sk.bytesize != C_secretkeybytes and sk.bytesize != C_legacysecretkeybytes ctx ||= '' raise ArgumentError, "ctx must be 255 bytes or smaller" if ctx.bytesize > 255 secret, pk = nil, nil if sk.bytesize == C_secretkeybytes secret, pk = sk[0, 57], sk[57, 114] elsif sk.bytesize == C_legacysecretkeybytes secret, pk = sk[0, 32], sk[32, 89] end khash = JOSE::JWA::SHA3.shake256(secret, 114) curve448_scalar, seed = khash[0, 57], khash[57, 114] curve448_scalar.setbyte(0, curve448_scalar.getbyte(0) & 252) curve448_scalar.setbyte(55, curve448_scalar.getbyte(55) | 128) curve448_scalar.setbyte(56, 0) a_s = OpenSSL::BN.new(curve448_scalar.reverse, 2).to_i # Calculate r_s and r (r only used in encoded form) r_s = (OpenSSL::BN.new(JOSE::JWA::SHA3.shake256(['SigEd448', 0, ctx.bytesize, ctx, seed, m].pack('a*CCa*a*a*'), 114).reverse, 2) % JOSE::JWA::Edwards448Point::L).to_i r = (C_B * r_s).encode() # Calculate h. h = (OpenSSL::BN.new(JOSE::JWA::SHA3.shake256(['SigEd448', 0, ctx.bytesize, ctx, r, pk, m].pack('a*CCa*a*a*a*'), 114).reverse, 2) % JOSE::JWA::Edwards448Point::L).to_i # Calculate s. s = OpenSSL::BN.new((r_s+h*a_s) % JOSE::JWA::Edwards448Point::L).to_s(2).rjust(C_bytes, JOSE::JWA::ZERO_PAD).reverse # The final signature is concatenation of r and s. return r+s end |
#sign_ph(m, sk, ctx = nil) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/jose/jwa/ed448.rb', line 85 def sign_ph(m, sk, ctx = nil) raise ArgumentError, "sk must be #{C_secretkeybytes} bytes" if sk.bytesize != C_secretkeybytes and sk.bytesize != C_legacysecretkeybytes ctx ||= '' raise ArgumentError, "ctx must be 255 bytes or smaller" if ctx.bytesize > 255 m = JOSE::JWA::SHA3.shake256(['SigEd448', 2, ctx.bytesize, ctx, m].pack('a*CCa*a*'), 64) secret, pk = nil, nil if sk.bytesize == C_secretkeybytes secret, pk = sk[0, 57], sk[57, 114] elsif sk.bytesize == C_legacysecretkeybytes secret, pk = sk[0, 32], sk[32, 89] end khash = JOSE::JWA::SHA3.shake256(secret, 114) curve448_scalar, seed = khash[0, 57], khash[57, 114] curve448_scalar.setbyte(0, curve448_scalar.getbyte(0) & 252) curve448_scalar.setbyte(55, curve448_scalar.getbyte(55) | 128) curve448_scalar.setbyte(56, 0) a_s = OpenSSL::BN.new(curve448_scalar.reverse, 2).to_i # Calculate r_s and r (r only used in encoded form) r_s = (OpenSSL::BN.new(JOSE::JWA::SHA3.shake256(['SigEd448', 1, ctx.bytesize, ctx, seed, m].pack('a*CCa*a*a*'), 114).reverse, 2) % JOSE::JWA::Edwards448Point::L).to_i r = (C_B * r_s).encode() # Calculate h. h = (OpenSSL::BN.new(JOSE::JWA::SHA3.shake256(['SigEd448', 1, ctx.bytesize, ctx, r, pk, m].pack('a*CCa*a*a*a*'), 114).reverse, 2) % JOSE::JWA::Edwards448Point::L).to_i # Calculate s. s = OpenSSL::BN.new((r_s+h*a_s) % JOSE::JWA::Edwards448Point::L).to_s(2).rjust(C_bytes, JOSE::JWA::ZERO_PAD).reverse # The final signature is concatenation of r and s. return r+s end |
#sk_to_curve448(sk) ⇒ Object
47 48 49 |
# File 'lib/jose/jwa/ed448.rb', line 47 def sk_to_curve448(sk) return secret_to_curve448(sk_to_secret(sk)) end |
#sk_to_pk(sk) ⇒ Object
41 42 43 44 45 |
# File 'lib/jose/jwa/ed448.rb', line 41 def sk_to_pk(sk) return sk[C_secretbytes, C_secretkeybytes] if sk.bytesize == C_secretkeybytes return sk[C_legacysecretbytes, C_legacysecretkeybytes] if sk.bytesize == C_legacysecretkeybytes raise ArgumentError, "sk must be #{C_secretkeybytes} bytes" end |
#sk_to_secret(sk) ⇒ Object
35 36 37 38 39 |
# File 'lib/jose/jwa/ed448.rb', line 35 def sk_to_secret(sk) return sk[0, C_secretbytes] if sk.bytesize == C_secretkeybytes return sk[0, C_legacysecretbytes] if sk.bytesize == C_legacysecretkeybytes raise ArgumentError, "sk must be #{C_secretkeybytes} bytes" end |
#verify(sig, m, pk, ctx = nil) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/jose/jwa/ed448.rb', line 113 def verify(sig, m, pk, ctx = nil) ctx ||= '' raise ArgumentError, "ctx must be 255 bytes or smaller" if ctx.bytesize > 255 # Sanity-check sizes. return false if sig.bytesize != C_signaturebytes return false if pk.bytesize != C_publickeybytes # Split signature into R and S, and parse. r, s = sig[0, 57], sig[57, 114] r_p, s_s = C_B.decode(r), OpenSSL::BN.new(s.reverse, 2).to_i # Parse public key. a_p = C_B.decode(pk) # Check parse results. return false if r_p.nil? or a_p.nil? or s_s > JOSE::JWA::Edwards448Point::L # Calculate h. h = (OpenSSL::BN.new(JOSE::JWA::SHA3.shake256(['SigEd448', 0, ctx.bytesize, ctx, r, pk, m].pack('a*CCa*a*a*a*'), 114).reverse, 2) % JOSE::JWA::Edwards448Point::L).to_i # Calculate left and right sides of check eq. rhs = r_p + (a_p * h) lhs = C_B * s_s JOSE::JWA::Edwards448Point::C.times do lhs = lhs.double() rhs = rhs.double() end # Check eq. holds? return lhs == rhs end |
#verify_ph(sig, m, pk, ctx = nil) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/jose/jwa/ed448.rb', line 139 def verify_ph(sig, m, pk, ctx = nil) ctx ||= '' raise ArgumentError, "ctx must be 255 bytes or smaller" if ctx.bytesize > 255 m = JOSE::JWA::SHA3.shake256(['SigEd448', 2, ctx.bytesize, ctx, m].pack('a*CCa*a*'), 64) # Sanity-check sizes. return false if sig.bytesize != C_signaturebytes return false if pk.bytesize != C_publickeybytes # Split signature into R and S, and parse. r, s = sig[0, 57], sig[57, 114] r_p, s_s = C_B.decode(r), OpenSSL::BN.new(s.reverse, 2).to_i # Parse public key. a_p = C_B.decode(pk) # Check parse results. return false if r_p.nil? or a_p.nil? or s_s > JOSE::JWA::Edwards448Point::L # Calculate h. h = (OpenSSL::BN.new(JOSE::JWA::SHA3.shake256(['SigEd448', 1, ctx.bytesize, ctx, r, pk, m].pack('a*CCa*a*a*a*'), 114).reverse, 2) % JOSE::JWA::Edwards448Point::L).to_i # Calculate left and right sides of check eq. rhs = r_p + (a_p * h) lhs = C_B * s_s JOSE::JWA::Edwards448Point::C.times do lhs = lhs.double() rhs = rhs.double() end # Check eq. holds? return lhs == rhs end |