Class: Sandal::Sig::ES
- Inherits:
-
Object
- Object
- Sandal::Sig::ES
- Defined in:
- lib/sandal/sig/es.rb
Overview
Base implementation of the ECDSA-SHA family of signature algorithms.
Instance Attribute Summary collapse
-
#name ⇒ String
readonly
The JWA name of the algorithm.
Class Method Summary collapse
-
.decode_asn1_signature(signature) ⇒ OpenSSL::BN
Decodes an ASN.1 signature into a pair of BNs.
-
.decode_jws_signature(signature) ⇒ OpenSSL::BN
Decodes a JWS signature into a pair of BNs.
-
.encode_asn1_signature(r, s) ⇒ String
Encodes a pair of BNs into an ASN.1 signature.
-
.encode_jws_signature(r, s, prime_size) ⇒ String
Encodes a pair of BNs into a JWS signature.
Instance Method Summary collapse
-
#ensure_curve(key, curve_name) ⇒ void
protected
Ensures that a key has a specified curve name.
-
#initialize(sha_size, prime_size, key) ⇒ ES
constructor
Creates a new instance; it’s probably easier to use one of the subclass constructors.
-
#sign(payload) ⇒ String
Signs a payload and returns the signature.
-
#valid?(signature, payload) ⇒ Boolean
Validates a payload signature and returns whether the signature matches.
Constructor Details
#initialize(sha_size, prime_size, key) ⇒ ES
Creates a new instance; it’s probably easier to use one of the subclass constructors.
17 18 19 20 21 22 |
# File 'lib/sandal/sig/es.rb', line 17 def initialize(sha_size, prime_size, key) @name = "ES#{sha_size}" @digest = OpenSSL::Digest.new("sha#{sha_size}") @prime_size = prime_size @key = key end |
Instance Attribute Details
#name ⇒ String (readonly)
Returns The JWA name of the algorithm.
10 11 12 |
# File 'lib/sandal/sig/es.rb', line 10 def name @name end |
Class Method Details
.decode_asn1_signature(signature) ⇒ OpenSSL::BN
Decodes an ASN.1 signature into a pair of BNs.
51 52 53 54 |
# File 'lib/sandal/sig/es.rb', line 51 def self.decode_asn1_signature(signature) asn_seq = OpenSSL::ASN1.decode(signature) return asn_seq.value[0].value, asn_seq.value[1].value end |
.decode_jws_signature(signature) ⇒ OpenSSL::BN
Decodes a JWS signature into a pair of BNs.
70 71 72 73 74 75 76 |
# File 'lib/sandal/sig/es.rb', line 70 def self.decode_jws_signature(signature) n_length = signature.length / 2 s_to_n = -> s { OpenSSL::BN.new(s.unpack('H*')[0], 16) } r = s_to_n.call(signature[0..(n_length - 1)]) s = s_to_n.call(signature[n_length..-1]) return r, s end |
.encode_asn1_signature(r, s) ⇒ String
Encodes a pair of BNs into an ASN.1 signature.
61 62 63 64 |
# File 'lib/sandal/sig/es.rb', line 61 def self.encode_asn1_signature(r, s) items = [OpenSSL::ASN1::Integer.new(r), OpenSSL::ASN1::Integer.new(s)] OpenSSL::ASN1::Sequence.new(items).to_der end |
.encode_jws_signature(r, s, prime_size) ⇒ String
Encodes a pair of BNs into a JWS signature.
84 85 86 87 88 |
# File 'lib/sandal/sig/es.rb', line 84 def self.encode_jws_signature(r, s, prime_size) byte_count = (prime_size / 8.0).ceil n_to_s = -> n { [n.to_s(16)].pack('H*').rjust(byte_count, "\0") } n_to_s.call(r) + n_to_s.call(s) end |
Instance Method Details
#ensure_curve(key, curve_name) ⇒ void (protected)
This method returns an undefined value.
Ensures that a key has a specified curve name.
98 99 100 |
# File 'lib/sandal/sig/es.rb', line 98 def ensure_curve(key, curve_name) raise ArgumentError, "The key must be in the #{curve_name} group." unless key.group.curve_name == curve_name end |
#sign(payload) ⇒ String
Signs a payload and returns the signature.
28 29 30 31 32 33 |
# File 'lib/sandal/sig/es.rb', line 28 def sign(payload) hash = @digest.digest(payload) asn1_sig = @key.dsa_sign_asn1(hash) r, s = self.class.decode_asn1_signature(asn1_sig) self.class.encode_jws_signature(r, s, @prime_size) end |
#valid?(signature, payload) ⇒ Boolean
Validates a payload signature and returns whether the signature matches.
40 41 42 43 44 45 |
# File 'lib/sandal/sig/es.rb', line 40 def valid?(signature, payload) hash = @digest.digest(payload) r, s = self.class.decode_jws_signature(signature) asn1_sig = self.class.encode_asn1_signature(r, s) @key.dsa_verify_asn1(hash, asn1_sig) end |