Module: XRBP::Crypto::Key
- Defined in:
- lib/xrbp/crypto/key.rb
Constant Summary collapse
- TOKEN_TYPES =
{ :none => 1, # unused :node_public => 28, :node_private => 32, :account_id => 0, :account_public => 35, :account_secret => 34, :family_generator => 41, :family_seed => 33 }
Class Method Summary collapse
-
.ed25519(seed = nil) ⇒ Hash
New ed25519 key pair (both public and private components).
-
.secp256k1(seed = nil) ⇒ Hash
New secp256k1 key pair (both public and private components).
-
.sign_digest(key, data) ⇒ String
Sign the digest using the specified key, returning the result.
-
.verify(key, data, expected) ⇒ Bool
Returns bool indicating if data is the result of signing expected value with given key.
Class Method Details
.ed25519(seed = nil) ⇒ Hash
Returns new ed25519 key pair (both public and private components).
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/xrbp/crypto/key.rb', line 63 def self.ed25519(seed=nil) # XXX openssl 1.1.1 needed for EdDSA support: # https://www.openssl.org/blog/blog/2018/09/11/release111/ # Until then use this: require "ed25519" sd, pk = nil if seed sd,pk = seed,seed else sd = Crypto.seed[:seed] pk = Crypto.parse_seed(sd) end sha512 = OpenSSL::Digest::SHA512.new pk = sha512.digest(pk)[0..31] key = Ed25519::SigningKey.new(pk) { :public => key.verify_key.to_bytes.unpack("H*").first.upcase, :private => key.to_bytes.unpack("H*").first.upcase, :seed => sd, :type => :ed25519 } end |
.secp256k1(seed = nil) ⇒ Hash
Returns new secp256k1 key pair (both public and private components).
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/xrbp/crypto/key.rb', line 20 def self.secp256k1(seed=nil) # XXX: the bitcoin secp256k1 implementation (which rippled pulls in / vendors) # has alot of nuances which require special configuration in openssl. For # the time being, mitigate this by pulling in & using the ruby # btc-secp256k1 bindings: # https://github.com/cryptape/ruby-bitcoin-secp256k1 # # Perhaps at some point, we can look into implementing this logic in pure-ruby: # https://medium.com/coinmonks/introduction-to-blockchains-bedrock-the-elliptic-curve-secp256k1-e4bd3bc17d require 'secp256k1' spk = Secp256k1::PrivateKey.new sd, pk = nil if seed sd,pk = seed,seed else sd = Crypto.seed[:seed] pk = Crypto.parse_seed(sd) end # FIXME: rippled & ripple-keypairs (& by extension ripple-lib) repeatedly # hash seed until certain it is less than the order of the # curve, we should do this as well (for security) # # https://github.com/ripple/rippled/blob/develop/src/ripple/crypto/impl/GenerateDeterministicKey.cpp # https://github.com/ripple/ripple-keypairs/blob/master/src/secp256k1.js # # Also look into if setting raw key here has same effect as # secp256k1.mul (as invoked in keypairs) sha512 = OpenSSL::Digest::SHA512.new pk = sha512.digest(pk)[0..31] spk.set_raw_privkey pk { :public => spk.pubkey.serialize.unpack("H*").first, :private => spk.send(:serialize), :seed => sd, :type => :secp256k1 } end |
.sign_digest(key, data) ⇒ String
Sign the digest using the specified key, returning the result
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/xrbp/crypto/key.rb', line 95 def self.sign_digest(key, data) raise "unknown key" unless key.is_a?(Hash) && key[:type] && key[:private] raise "invalid data" unless data.length == 32 if key[:type] == :secp256k1 require 'secp256k1' pk = Secp256k1::PrivateKey.new pk.set_raw_privkey [key[:private]].pack("H*") sig_raw = pk.ecdsa_sign data, raw: true return pk.ecdsa_serialize sig_raw elsif key[:type] == :ed25519 require "ed25519" sd = key[:seed] pk = Crypto.parse_seed(sd) sha512 = OpenSSL::Digest::SHA512.new pk = sha512.digest(pk)[0..31] pk = Ed25519::SigningKey.new(pk) return pk.sign(data) end raise "unknown key type" end |
.verify(key, data, expected) ⇒ Bool
Returns bool indicating if data is the result of signing expected value with given key.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/xrbp/crypto/key.rb', line 131 def self.verify(key, data, expected) if key[:type] == :secp256k1 require 'secp256k1' pb = Secp256k1::PublicKey.new :pubkey => [key[:public]].pack("H*"), :raw => true pv = Secp256k1::PrivateKey.new return pb.ecdsa_verify expected, pv.ecdsa_deserialize(data), raw: true elsif key[:type] == :ed25519 require "ed25519" pk = Ed25519::VerifyKey.new([key[:public]].pack("H*")) begin return pk.verify(data, expected) rescue Ed25519::VerifyError return false end end raise "unknown key type" end |