Module: Runar::RabinSig
- Defined in:
- lib/runar/rabin_sig.rb
Class Method Summary collapse
-
.rabin_verify(msg_hex, sig_hex, pad_hex, pubkey_hex) ⇒ Boolean
Verify a Rabin signature.
Class Method Details
.rabin_verify(msg_hex, sig_hex, pad_hex, pubkey_hex) ⇒ Boolean
Verify a Rabin signature.
All parameters are hex-encoded strings. sig, padding, and pubkey are interpreted as unsigned little-endian integers.
— No domain separation —
The message is hashed directly (SHA-256(msg)) without any domain prefix or context tag. This is inherent to the Rabin signature scheme as used in Bitcoin Script contracts: the locking script encodes the raw hash check, so introducing a domain prefix would change the expected hash value and break existing deployed contracts.
The practical implication is that two different applications using the same Rabin key could have cross-signature validity: a signature produced for application A’s message is also a valid Rabin signature for that same byte sequence in application B. Callers are responsible for ensuring messages are structurally distinct across use cases (e.g. by including a contract-specific nonce or type tag in the message before signing).
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/runar/rabin_sig.rb', line 44 def self.rabin_verify(msg_hex, sig_hex, pad_hex, pubkey_hex) n = bytes_to_unsigned_le([pubkey_hex].pack('H*')) return false if n <= 0 sig_int = bytes_to_unsigned_le([sig_hex].pack('H*')) pad_int = bytes_to_unsigned_le([pad_hex].pack('H*')) msg_bytes = [msg_hex].pack('H*') hash_bytes = Digest::SHA256.digest(msg_bytes) hash_int = bytes_to_unsigned_le(hash_bytes) lhs = (sig_int * sig_int + pad_int) % n rhs = hash_int % n lhs == rhs end |