Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions lib/ed25519/verify_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
module Ed25519
# Public key for verifying digital signatures
class VerifyKey
SCALAR_ORDER = [
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
].pack("C*").freeze
private_constant :SCALAR_ORDER

# Create a Ed25519::VerifyKey from its serialized Twisted Edwards representation
#
# @param key [String] 32-byte string representing a serialized public key
Expand All @@ -20,11 +28,11 @@ def initialize(key)
#
# @return [true] message verified successfully
def verify(signature, message)
if signature.length != SIGNATURE_SIZE
raise ArgumentError, "expected #{SIGNATURE_SIZE} byte signature, got #{signature.length}"
if signature.bytesize != SIGNATURE_SIZE
raise ArgumentError, "expected #{SIGNATURE_SIZE} byte signature, got #{signature.bytesize}"
end

return true if Ed25519.provider.verify(@key_bytes, signature, message)
return true if canonical_scalar?(signature) && Ed25519.provider.verify(@key_bytes, signature, message)

raise VerifyError, "signature verification failed!"
end
Expand All @@ -41,5 +49,17 @@ def to_bytes
def inspect
"#<#{self.class}:#{@key_bytes.unpack1('H*')}>"
end

private

def canonical_scalar?(signature)
(KEY_SIZE - 1).downto(0) do |index|
scalar_byte = signature.getbyte(KEY_SIZE + index)
order_byte = SCALAR_ORDER.getbyte(index)
return scalar_byte < order_byte if scalar_byte != order_byte
end

false
end
end
end