Module: Bech32
- Defined in:
- lib/bech32.rb,
lib/bech32/nostr.rb,
lib/bech32/version.rb,
lib/bech32/nostr/nip19.rb,
lib/bech32/segwit_addr.rb,
lib/bech32/nostr/entity.rb,
lib/bech32/silent_payment_addr.rb,
sig/bech32/bech32.rbs,
sig/bech32/nostr/nip19.rbs,
sig/bech32/segwit_addr.rbs,
sig/bech32/nostr/entity.rbs,
sig/bech32/silent_payment_addr.rbs
Defined Under Namespace
Modules: Encoding, Nostr Classes: SegwitAddr, SilentPaymentAddr
Constant Summary collapse
- SEPARATOR =
'1'- CHARSET =
%w(q p z r y 9 x 8 g f 2 t v d w 0 s 3 j n 5 4 k h c e 6 m u a 7 l)
- BECH32M_CONST =
0x2bc830a3- VERSION =
'1.5.1'
Class Method Summary collapse
-
.convert_bits(data, from, to, padding = true) ⇒ Array[Integer]?
Convert bits from one base to another.
-
.create_checksum(hrp, data, spec) ⇒ Array[Integer]
Create checksum for hrp and data.
-
.decode(bech, max_length = 90) ⇒ [String, Array[Integer], Integer]?
Decode bech32/bech32m string.
-
.encode(hrp, data, spec) ⇒ String
Encode hrp and data to bech32/bech32m string.
-
.verify_checksum(hrp, data) ⇒ Integer?
Verify checksum.
Instance Method Summary collapse
-
#convert_bits(data, from, to, padding = true) ⇒ Array[Integer]?
Convert bits from one base to another.
-
#create_checksum(hrp, data, spec) ⇒ Array[Integer]
Create checksum for hrp and data.
-
#decode(bech, max_length = 90) ⇒ [String, Array[Integer], Integer]?
Decode bech32/bech32m string.
-
#encode(hrp, data, spec) ⇒ String
module_function methods are also available as instance methods.
-
#expand_hrp(hrp) ⇒ Array[Integer]
Expand HRP for checksum computation.
-
#polymod(values) ⇒ Integer
Compute polymod checksum.
-
#verify_checksum(hrp, data) ⇒ Integer?
Verify checksum.
Class Method Details
.convert_bits(data, from, to, padding = true) ⇒ Array[Integer]?
Convert bits from one base to another.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/bech32.rb', line 97 def convert_bits(data, from, to, padding=true) acc = 0 bits = 0 ret = [] maxv = (1 << to) - 1 max_acc = (1 << (from + to - 1)) - 1 data.each do |v| return nil if v < 0 || (v >> from) != 0 acc = ((acc << from) | v) & max_acc bits += from while bits >= to bits -= to ret << ((acc >> bits) & maxv) end end if padding ret << ((acc << (to - bits)) & maxv) unless bits == 0 elsif bits >= from || ((acc << (to - bits)) & maxv) != 0 return nil end ret end |
.create_checksum(hrp, data, spec) ⇒ Array[Integer]
Create checksum for hrp and data.
65 66 67 68 69 70 |
# File 'lib/bech32.rb', line 65 def create_checksum(hrp, data, spec) values = (hrp) + data const = (spec == Bech32::Encoding::BECH32M ? Bech32::BECH32M_CONST : 1) polymod = polymod(values + [0, 0, 0, 0, 0, 0]) ^ const (0..5).map{|i|(polymod >> 5 * (5 - i)) & 31} end |
.decode(bech, max_length = 90) ⇒ [String, Array[Integer], Integer]?
Decode bech32/bech32m string. Returns nil if invalid.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/bech32.rb', line 46 def decode(bech, max_length = 90) # check uppercase/lowercase return nil if bech.bytes.index{|x| x < 33 || x > 126} return nil if (bech.downcase != bech && bech.upcase != bech) bech = bech.downcase # check data length pos = bech.rindex(SEPARATOR) return nil if pos.nil? || pos < 1 || pos + 7 > bech.length || bech.length > max_length # check valid charset bech[pos+1..-1].each_char{|c|return nil unless CHARSET.include?(c)} # split hrp and data hrp = bech[0..pos-1] data = bech[pos+1..-1].each_char.map{|c|CHARSET.index(c)} # check checksum spec = verify_checksum(hrp, data) spec ? [hrp, data[0..-7], spec] : nil end |
.encode(hrp, data, spec) ⇒ String
Encode hrp and data to bech32/bech32m string.
29 30 31 32 |
# File 'lib/bech32.rb', line 29 def encode(hrp, data, spec) checksummed = data + create_checksum(hrp, data, spec) hrp + SEPARATOR + checksummed.map{|i|CHARSET[i]}.join end |
.verify_checksum(hrp, data) ⇒ Integer?
Verify checksum. Returns encoding spec if valid, nil otherwise.
76 77 78 79 80 81 82 83 84 |
# File 'lib/bech32.rb', line 76 def verify_checksum(hrp, data) const = polymod((hrp) + data) case const when 1 Encoding::BECH32 when BECH32M_CONST Encoding::BECH32M end end |
Instance Method Details
#convert_bits(data, from, to, padding = true) ⇒ Array[Integer]?
Convert bits from one base to another.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/bech32.rb', line 97 def convert_bits(data, from, to, padding=true) acc = 0 bits = 0 ret = [] maxv = (1 << to) - 1 max_acc = (1 << (from + to - 1)) - 1 data.each do |v| return nil if v < 0 || (v >> from) != 0 acc = ((acc << from) | v) & max_acc bits += from while bits >= to bits -= to ret << ((acc >> bits) & maxv) end end if padding ret << ((acc << (to - bits)) & maxv) unless bits == 0 elsif bits >= from || ((acc << (to - bits)) & maxv) != 0 return nil end ret end |
#create_checksum(hrp, data, spec) ⇒ Array[Integer]
Create checksum for hrp and data.
65 66 67 68 69 70 |
# File 'lib/bech32.rb', line 65 def create_checksum(hrp, data, spec) values = (hrp) + data const = (spec == Bech32::Encoding::BECH32M ? Bech32::BECH32M_CONST : 1) polymod = polymod(values + [0, 0, 0, 0, 0, 0]) ^ const (0..5).map{|i|(polymod >> 5 * (5 - i)) & 31} end |
#decode(bech, max_length = 90) ⇒ [String, Array[Integer], Integer]?
Decode bech32/bech32m string. Returns nil if invalid.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/bech32.rb', line 46 def decode(bech, max_length = 90) # check uppercase/lowercase return nil if bech.bytes.index{|x| x < 33 || x > 126} return nil if (bech.downcase != bech && bech.upcase != bech) bech = bech.downcase # check data length pos = bech.rindex(SEPARATOR) return nil if pos.nil? || pos < 1 || pos + 7 > bech.length || bech.length > max_length # check valid charset bech[pos+1..-1].each_char{|c|return nil unless CHARSET.include?(c)} # split hrp and data hrp = bech[0..pos-1] data = bech[pos+1..-1].each_char.map{|c|CHARSET.index(c)} # check checksum spec = verify_checksum(hrp, data) spec ? [hrp, data[0..-7], spec] : nil end |
#encode(hrp, data, spec) ⇒ String
module_function methods are also available as instance methods
29 30 31 32 |
# File 'lib/bech32.rb', line 29 def encode(hrp, data, spec) checksummed = data + create_checksum(hrp, data, spec) hrp + SEPARATOR + checksummed.map{|i|CHARSET[i]}.join end |
#expand_hrp(hrp) ⇒ Array[Integer]
Expand HRP for checksum computation.
87 88 89 |
# File 'lib/bech32.rb', line 87 def (hrp) hrp.each_char.map{|c|c.ord >> 5} + [0] + hrp.each_char.map{|c|c.ord & 31} end |
#polymod(values) ⇒ Integer
Compute polymod checksum.
121 122 123 124 125 126 127 128 129 130 |
# File 'lib/bech32.rb', line 121 def polymod(values) generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] chk = 1 values.each do |v| top = chk >> 25 chk = (chk & 0x1ffffff) << 5 ^ v (0..4).each{|i|chk ^= ((top >> i) & 1) == 0 ? 0 : generator[i]} end chk end |
#verify_checksum(hrp, data) ⇒ Integer?
Verify checksum. Returns encoding spec if valid, nil otherwise.
76 77 78 79 80 81 82 83 84 |
# File 'lib/bech32.rb', line 76 def verify_checksum(hrp, data) const = polymod((hrp) + data) case const when 1 Encoding::BECH32 when BECH32M_CONST Encoding::BECH32M end end |