Class: Sidetree::Key
- Inherits:
-
Object
- Object
- Sidetree::Key
- Defined in:
- lib/sidetree/key.rb
Instance Attribute Summary collapse
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#private_key ⇒ Object
readonly
Returns the value of attribute private_key.
-
#public_key ⇒ Object
readonly
Returns the value of attribute public_key.
-
#purposes ⇒ Object
readonly
Returns the value of attribute purposes.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Class Method Summary collapse
-
.from_jwk(data) ⇒ Sidetree::Key
Generate key instance from jwk Hash.
-
.generate(id: nil, purposes: [], type: Sidetree::Params::DEFAULT_PUBKEY_TYPE) ⇒ Sidetree::Key
Generate Secp256k1 key.
-
.valid_private_key?(private_key) ⇒ Boolean
Check whether private is valid range.
Instance Method Summary collapse
-
#encoded_private_key ⇒ String
Return base64 encoded private key.
-
#initialize(private_key: nil, public_key: nil, id: nil, purposes: [], type: Sidetree::Params::DEFAULT_PUBKEY_TYPE) ⇒ Key
constructor
A new instance of Key.
-
#jws_sign_key ⇒ OpenSSL::PKey::EC
Convert the private key to the format (OpenSSL::PKey::EC) in which it will be signed in JWS.
-
#to_commitment ⇒ String
Generate commitment for this key.
- #to_h ⇒ Object
-
#to_jwk(include_privkey: false) ⇒ JSON::JWK
Generate JSON::JWK object.
-
#to_reveal_value ⇒ String
Generate reveal value for this key.
Constructor Details
#initialize(private_key: nil, public_key: nil, id: nil, purposes: [], type: Sidetree::Params::DEFAULT_PUBKEY_TYPE) ⇒ Key
Returns a new instance of Key.
10 11 12 13 14 15 16 17 18 19 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 |
# File 'lib/sidetree/key.rb', line 10 def initialize( private_key: nil, public_key: nil, id: nil, purposes: [], type: Sidetree::Params::DEFAULT_PUBKEY_TYPE ) if private_key unless Key.valid_private_key?(private_key) raise Error, "private key is invalid range." end @private_key = private_key pub = ECDSA::Group::Secp256k1.generator.multiply_by_scalar(private_key) if public_key unless pub == public_key raise Error, "Public and private keys do not match." end else public_key = pub end end unless public_key raise Error, "Specify either the private key or the public key" end unless public_key.is_a?(ECDSA::Point) raise Error, "public key must be an ECDSA::Point instance." end unless ECDSA::Group::Secp256k1.valid_public_key?(public_key) raise Error, "public key is invalid." end @public_key = public_key purposes.each do |purpose| if purpose && !Sidetree::OP::PublicKeyPurpose.values.include?(purpose) raise Error, "Unknown purpose '#{purpose}' specified." end end Sidetree::Validator.validate_id!(id) if id @purposes = purposes @id = id @type = type end |
Instance Attribute Details
#id ⇒ Object (readonly)
Returns the value of attribute id.
3 4 5 |
# File 'lib/sidetree/key.rb', line 3 def id @id end |
#private_key ⇒ Object (readonly)
Returns the value of attribute private_key.
3 4 5 |
# File 'lib/sidetree/key.rb', line 3 def private_key @private_key end |
#public_key ⇒ Object (readonly)
Returns the value of attribute public_key.
3 4 5 |
# File 'lib/sidetree/key.rb', line 3 def public_key @public_key end |
#purposes ⇒ Object (readonly)
Returns the value of attribute purposes.
3 4 5 |
# File 'lib/sidetree/key.rb', line 3 def purposes @purposes end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
3 4 5 |
# File 'lib/sidetree/key.rb', line 3 def type @type end |
Class Method Details
.from_jwk(data) ⇒ Sidetree::Key
Generate key instance from jwk Hash.
78 79 80 81 82 83 84 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 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/sidetree/key.rb', line 78 def self.from_jwk(data) key_data = data["publicKeyJwk"] ? data["publicKeyJwk"] : data key_type = key_data["kty"] curve = key_data["crv"] if key_type.nil? || key_type != "EC" raise Error, "Unsupported key type '#{key_type}' specified." end if curve.nil? || curve != "secp256k1" raise Error, "Unsupported curve '#{curve}' specified." end raise Error, "x property required." unless key_data["x"] raise Error, "y property required." unless key_data["y"] # `x` and `y` need 43 Base64URL encoded bytes to contain 256 bits. unless key_data["x"].length == 43 raise Error, "Secp256k1 JWK 'x' property must be 43 bytes." end unless key_data["y"].length == 43 raise Error, "Secp256k1 JWK 'y' property must be 43 bytes." end x = Base64.urlsafe_decode64(key_data["x"]) y = Base64.urlsafe_decode64(key_data["y"]) point = ECDSA::Format::PointOctetString.decode( ["04"].pack("H*") + x + y, ECDSA::Group::Secp256k1 ) private_key = if key_data["d"] Base64.urlsafe_decode64(key_data["d"]).unpack1("H*").to_i(16) else nil end purposes = data["purposes"] ? data["purposes"] : [] Key.new( public_key: point, private_key: private_key, purposes: purposes, id: data["id"], type: data["type"] ) end |
.generate(id: nil, purposes: [], type: Sidetree::Params::DEFAULT_PUBKEY_TYPE) ⇒ Sidetree::Key
Generate Secp256k1 key.
64 65 66 67 68 69 70 71 72 |
# File 'lib/sidetree/key.rb', line 64 def self.generate( id: nil, purposes: [], type: Sidetree::Params::DEFAULT_PUBKEY_TYPE ) private_key = 1 + SecureRandom.random_number(ECDSA::Group::Secp256k1.order - 1) Key.new(private_key: private_key, purposes: purposes, id: id, type: type) end |
.valid_private_key?(private_key) ⇒ Boolean
Check whether private is valid range.
126 127 128 |
# File 'lib/sidetree/key.rb', line 126 def self.valid_private_key?(private_key) 0x01 <= private_key && private_key < ECDSA::Group::Secp256k1.order end |
Instance Method Details
#encoded_private_key ⇒ String
Return base64 encoded private key.
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/sidetree/key.rb', line 188 def encoded_private_key if private_key Base64.urlsafe_encode64( [private_key.to_s(16).rjust(32 * 2, "0")].pack("H*"), padding: false ) else nil end end |
#jws_sign_key ⇒ OpenSSL::PKey::EC
Convert the private key to the format (OpenSSL::PKey::EC) in which it will be signed in JWS.
161 162 163 164 |
# File 'lib/sidetree/key.rb', line 161 def jws_sign_key return nil unless private_key to_jwk(include_privkey: true).to_key end |
#to_commitment ⇒ String
Generate commitment for this key.
168 169 170 171 |
# File 'lib/sidetree/key.rb', line 168 def to_commitment digest = Digest::SHA256.digest(to_jwk.normalize.to_json_c14n) Sidetree.to_hash(digest) end |
#to_h ⇒ Object
179 180 181 182 183 184 |
# File 'lib/sidetree/key.rb', line 179 def to_h h = { publicKeyJwk: to_jwk.normalize, purposes: purposes } h[:id] = id if id h[:type] = type if type h.stringify_keys end |
#to_jwk(include_privkey: false) ⇒ JSON::JWK
Generate JSON::JWK object.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/sidetree/key.rb', line 133 def to_jwk(include_privkey: false) jwk = Sidetree::Util::JWK.parse( kty: "EC", crv: "secp256k1", x: Base64.urlsafe_encode64( ECDSA::Format::FieldElementOctetString.encode( public_key.x, public_key.group.field ), padding: false ), y: Base64.urlsafe_encode64( ECDSA::Format::FieldElementOctetString.encode( public_key.y, public_key.group.field ), padding: false ) ) jwk["d"] = encoded_private_key if include_privkey && private_key jwk end |