Top Level Namespace
- Includes:
- Cryptos::Utils::Bytes
Defined Under Namespace
Modules: Cryptos
Constant Summary collapse
- EC_Gx =
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
- EC_Gy =
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
- EC_p =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
- EC_n =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
- LOW_S =
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
Instance Method Summary collapse
- #ec_add(ax, ay, bx, by, pn) ⇒ Object
- #ec_double(px, py, pn) ⇒ Object
- #ec_multiply(m, px, py, pn) ⇒ Object
-
#ecdsa_sign(private_key, digest, temp_key = nil) ⇒ Object
ECDSA.
- #ecdsa_verify?(px, py, digest, signature) ⇒ Boolean
- #extended_euclidean_algorithm(a, b) ⇒ Object
- #inverse(n, p) ⇒ Object
Methods included from Cryptos::Utils::Bytes
#bignum_to_bytes, #bytes_to_bignum
Instance Method Details
#ec_add(ax, ay, bx, by, pn) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/cryptos/elliptic_curve.rb', line 49 def ec_add(ax, ay, bx, by, pn) return [ax, ay] if bx == 0 && by == 0 return [bx, by] if ax == 0 && ay == 0 return ec_double(ax, ay, pn) if ax == bx && ay == by i_bax = inverse(ax - bx, pn) slope = ((ay - by) * i_bax) % pn x = (slope**2 - ax - bx) % pn y = (slope*(ax - x) - ay) % pn [x, y] end |
#ec_double(px, py, pn) ⇒ Object
42 43 44 45 46 47 48 |
# File 'lib/cryptos/elliptic_curve.rb', line 42 def ec_double(px, py, pn) i_2y = inverse(2 * py, pn) slope = (3 * px**2 * i_2y) % pn x = (slope**2 - 2 * px) % pn y = (slope*(px - x) - py) % pn [x, y] end |
#ec_multiply(m, px, py, pn) ⇒ Object
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/cryptos/elliptic_curve.rb', line 60 def ec_multiply(m, px, py, pn) nx, ny = px, py qx, qy = 0, 0 while m > 0 qx, qy = ec_add qx, qy, nx, ny, pn if m&1 == 1 nx, ny = ec_double nx, ny, pn m >>= 1 end [qx, qy] end |
#ecdsa_sign(private_key, digest, temp_key = nil) ⇒ Object
ECDSA
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/cryptos/elliptic_curve.rb', line 74 def ecdsa_sign(private_key, digest, temp_key = nil) temp_key ||= Cryptos::PrivateKey.generate.value rx, _ry = ec_multiply(temp_key, EC_Gx, EC_Gy, EC_p) r = rx % EC_n r > 0 || raise('r is zero, try again new temp key') i_tk = inverse temp_key, EC_n m = bytes_to_bignum digest s = (i_tk * (m + r * private_key)) % EC_n s > 0 || raise('s is zero, try again new temp key') if s > LOW_S # https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures # puts 'WARN: s is too big, use low s values' s = (EC_n - s) % EC_n end [r, s] end |
#ecdsa_verify?(px, py, digest, signature) ⇒ Boolean
91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/cryptos/elliptic_curve.rb', line 91 def ecdsa_verify?(px, py, digest, signature) r, s = signature i_s = inverse s, EC_n m = bytes_to_bignum digest u1 = i_s * m % EC_n u2 = i_s * r % EC_n u1Gx, u1Gy = ec_multiply u1, EC_Gx, EC_Gy, EC_p u2Px, u2Py = ec_multiply u2, px, py, EC_p rx, _ry = ec_add u1Gx, u1Gy, u2Px, u2Py, EC_p r == rx end |
#extended_euclidean_algorithm(a, b) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/cryptos/elliptic_curve.rb', line 24 def extended_euclidean_algorithm(a, b) s, old_s = 0, 1 t, old_t = 1, 0 r, old_r = b, a while r != 0 quotient = old_r / r old_r, r = r, old_r - quotient * r old_s, s = s, old_s - quotient * s old_t, t = t, old_t - quotient * t end [old_r, old_s, old_t] end |
#inverse(n, p) ⇒ Object
36 37 38 39 40 41 |
# File 'lib/cryptos/elliptic_curve.rb', line 36 def inverse(n, p) gcd, x, y = extended_euclidean_algorithm(n, p) (n * x + p * y) % p == gcd || raise('invalid gcd') gcd == 1 || raise('no multiplicative inverse') x % p end |