[UNSTABLE] Remove b64, add b32

This commit is contained in:
Netscape Navigator 2020-04-05 19:38:37 -05:00
parent 96e2025dc9
commit 30d6690b1c
9 changed files with 63 additions and 141 deletions

View File

@ -1,126 +0,0 @@
require_relative "./dist/pigeon"
require "pry"
# http://www.crockford.com/wrmg/base32.html
class Base32
ENCODER = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"J",
"K",
"M",
"N",
"P",
"Q",
"R",
"S",
"T",
"V",
"W",
"X",
"Y",
"Z",
].freeze
DECODER = {
"0" => 0,
"O" => 0,
"1" => 1,
"I" => 1,
"L" => 1,
"2" => 2,
"3" => 3,
"4" => 4,
"5" => 5,
"6" => 6,
"7" => 7,
"8" => 8,
"9" => 9,
"A" => 10,
"B" => 11,
"C" => 12,
"D" => 13,
"E" => 14,
"F" => 15,
"G" => 16,
"H" => 17,
"J" => 18,
"K" => 19,
"M" => 20,
"N" => 21,
"P" => 22,
"Q" => 23,
"R" => 24,
"S" => 25,
"T" => 26,
"V" => 27,
"W" => 28,
"X" => 29,
"Y" => 30,
"Z" => 31,
}.freeze
def self.encode(string)
string
.each_byte
.to_a
.map { |x| x.to_s(2).rjust(8, "0") }
.join
.scan(/.{1,5}/)
.map { |x| x.rjust(5, "0") }
.map { |bits| ENCODER.fetch(bits.to_i(2)) }
.join
end
def self.decode(string)
string
.split("")
.map { |x| DECODER.fetch(x.upcase) }
.map { |x| x.to_s(2).rjust(5, "0") }
.join("")
.scan(/.{1,8}/)
.map do |x|
# This is where problems start.
# binding.pry if x.length != 5
x.to_i(2).chr
end
.join("")
end
end
[
"How razorback jumping frogs can level six piqued gymnasts.",
"Sixty zippers were quickly picked from the woven jute bag.",
"Crazy Fredrick bought many very exquisite opal jewels.",
"Jump by vow of quick, lazy strength in Oxford.",
"The quick brown fox jumps over a lazy dog.",
"How quickly daft jumping zebras vex.",
"Sphinx of black quartz: judge my vow.",
"Quick zephyrs blow, vexing daft Jim.",
"Waltz, nymph, for quick jigs vex bud.",
].select do |x|
puts "==="
y = Base32.encode(x)
z = Base32.decode(y)
puts y
puts z
puts x
end

52
dist/pigeon.rb vendored
View File

@ -59,6 +59,54 @@ module Pigeon
# /Constants for internal use only # /Constants for internal use only
class Helpers class Helpers
B32_ENC = {
"00000" => "0", "00001" => "1", "00010" => "2", "00011" => "3",
"00100" => "4", "00101" => "5", "00110" => "6", "00111" => "7",
"01000" => "8", "01001" => "9", "01010" => "A", "01011" => "B",
"01100" => "C", "01101" => "D", "01110" => "E", "01111" => "F",
"10000" => "G", "10001" => "H", "10010" => "J", "10011" => "K",
"10100" => "M", "10101" => "N", "10110" => "P", "10111" => "Q",
"11000" => "R", "11001" => "S", "11010" => "T", "11011" => "V",
"11100" => "W", "11101" => "X", "11110" => "Y", "11111" => "Z",
}.freeze
B32_DEC = {
"0" => 0b00000, "O" => 0b00000, "1" => 0b00001, "I" => 0b00001,
"L" => 0b00001, "2" => 0b00010, "3" => 0b00011, "4" => 0b00100,
"5" => 0b00101, "6" => 0b00110, "7" => 0b00111, "8" => 0b01000,
"9" => 0b01001, "A" => 0b01010, "B" => 0b01011, "C" => 0b01100,
"D" => 0b01101, "E" => 0b01110, "F" => 0b01111, "G" => 0b10000,
"H" => 0b10001, "J" => 0b10010, "K" => 0b10011, "M" => 0b10100,
"N" => 0b10101, "P" => 0b10110, "Q" => 0b10111, "R" => 0b11000,
"S" => 0b11001, "T" => 0b11010, "V" => 0b11011, "W" => 0b11100,
"X" => 0b11101, "Y" => 0b11110, "Z" => 0b11111,
}.freeze
# http://www.crockford.com/wrmg/base32.html
def self.b32_encode(string)
string
.each_byte
.to_a
.map { |x| x.to_s(2).rjust(8, "0") }
.join
.scan(/.{1,5}/)
.map { |x| x.ljust(5, "0") }
.map { |bits| B32_ENC.fetch(bits) }
.join
end
# http://www.crockford.com/wrmg/base32.html
def self.b32_decode(string)
string
.split("")
.map { |x| B32_DEC.fetch(x.upcase) }
.map { |x| x.to_s(2).rjust(5, "0") }
.join("")
.scan(/.{1,8}/)
.map { |x| x.length == 8 ? x.to_i(2).chr : "" }
.join("")
end
def self.create_message(kind, params) def self.create_message(kind, params)
draft = Pigeon::Draft.create(kind: kind) draft = Pigeon::Draft.create(kind: kind)
params.map { |(k, v)| draft[k] = v } params.map { |(k, v)| draft[k] = v }
@ -77,9 +125,9 @@ module Pigeon
def self.decode_multihash(string) def self.decode_multihash(string)
if string[SIG_RANGE] == SIG_FOOTER if string[SIG_RANGE] == SIG_FOOTER
return Base64.urlsafe_decode64(string.gsub(SIG_FOOTER, "")) return b32_decode(string.gsub(SIG_FOOTER, ""))
else else
return Base64.urlsafe_decode64(string[1..].gsub(FOOTERS_REGEX, "")) return b32_decode(string[1..].gsub(FOOTERS_REGEX, ""))
end end
end end
end end

View File

@ -5,10 +5,10 @@ module Pigeon
# TODO: Create regexes using string and Regexp.new() for cleaner regexes. # TODO: Create regexes using string and Regexp.new() for cleaner regexes.
DEPTH_COUNT = /\d{1,7}/ DEPTH_COUNT = /\d{1,7}/
NULL_VALUE = /NONE/ NULL_VALUE = /NONE/
FEED_VALUE = /@.{44}\.ed25519/ FEED_VALUE = /@.{52}\.ed25519/
MESG_VALUE = /%.{44}\.sha256/ MESG_VALUE = /%.{52}\.sha256/
BLOB_VALUE = /&.{44}\.sha256/ BLOB_VALUE = /&.{52}\.sha256/
STRG_VALUE = /".{1,90}"/ STRG_VALUE = /".{1,128}"/
# If you need other characters (but not spaces) submit an issue. # If you need other characters (but not spaces) submit an issue.
ALPHANUMERICISH = /[a-zA-Z0-9_\-=\.]{1,90}/ ALPHANUMERICISH = /[a-zA-Z0-9_\-=\.]{1,90}/
ALL_VALUES = [ ALL_VALUES = [

View File

@ -27,19 +27,19 @@ module Pigeon
end end
def private_key def private_key
@private_key ||= Base64.urlsafe_encode64(@seed) @private_key ||= Helpers.b32_encode(@seed)
end end
def public_key def public_key
bytes = @signing_key.verify_key.to_bytes bytes = @signing_key.verify_key.to_bytes
b64 = Base64.urlsafe_encode64(bytes) b64 = Helpers.b32_encode(bytes)
@public_key ||= [IDENTITY_SIGIL, b64, IDENTITY_FOOTER].join("") @public_key ||= [IDENTITY_SIGIL, b64, IDENTITY_FOOTER].join("")
end end
def sign(string) def sign(string)
hex = @signing_key.sign(string) hex = @signing_key.sign(string)
b64 = Base64.urlsafe_encode64(hex) b64 = Helpers.b32_encode(hex)
return b64 + SIG_FOOTER return b64 + SIG_FOOTER
end end

View File

@ -41,7 +41,7 @@ module Pigeon
end end
def multihash def multihash
sha256 = Base64.urlsafe_encode64(Digest::SHA256.digest(self.render)) sha256 = Helpers.b32_encode(Digest::SHA256.digest(self.render))
"#{MESSAGE_SIGIL}#{sha256}#{BLOB_FOOTER}" "#{MESSAGE_SIGIL}#{sha256}#{BLOB_FOOTER}"
end end

View File

@ -72,7 +72,7 @@ module Pigeon
def set_blob(data) def set_blob(data)
raw_digest = Digest::SHA256.digest(data) raw_digest = Digest::SHA256.digest(data)
b64_digest = Base64.urlsafe_encode64(raw_digest) b64_digest = Helpers.b32_encode(raw_digest)
multihash = [BLOB_SIGIL, b64_digest, BLOB_FOOTER].join("") multihash = [BLOB_SIGIL, b64_digest, BLOB_FOOTER].join("")
write { store[BLOB_NS][multihash] = data } write { store[BLOB_NS][multihash] = data }

View File

@ -35,7 +35,7 @@ module Pigeon
puts kp.public_key puts kp.public_key
end end
desc "show", "Prints a base64 identiy string to STDOUT" desc "show", "Prints your identiy string to STDOUT"
def show def show
puts Pigeon::LocalIdentity.current.public_key puts Pigeon::LocalIdentity.current.public_key

View File

@ -30,7 +30,7 @@ RSpec.describe Pigeon::LocalIdentity do
Pigeon::IDENTITY_FOOTER, Pigeon::IDENTITY_FOOTER,
].join("") ].join("")
result = Pigeon::Helpers.decode_multihash(example) result = Pigeon::Helpers.decode_multihash(example)
expect(result).to eq(Base64.urlsafe_decode64(whatever)) expect(result).to eq(Pigeon::Helpers.b32_decode(whatever))
end end
it "caches LocalIdentity.current" do it "caches LocalIdentity.current" do

View File

@ -113,8 +113,8 @@ RSpec.describe Pigeon::Message do
combinations = [[key1, sig1], [key1, sig2], [key2, sig1], [key2, sig2]] combinations = [[key1, sig1], [key1, sig2], [key2, sig1], [key2, sig2]]
combinations.map { |(key, sig)| key.verify_key.verify(sig, plaintext) } combinations.map { |(key, sig)| key.verify_key.verify(sig, plaintext) }
sig1_b64 = Base64.urlsafe_encode64(sig1) + Pigeon::SIG_FOOTER sig1_b64 = Pigeon::Helpers.b32_encode(sig1) + Pigeon::SIG_FOOTER
sig2_b64 = Base64.urlsafe_encode64(sig2) + Pigeon::SIG_FOOTER sig2_b64 = Pigeon::Helpers.b32_encode(sig2) + Pigeon::SIG_FOOTER
expect(message.signature).to eq(sig1_b64) expect(message.signature).to eq(sig1_b64)
expect(message.signature).to eq(sig2_b64) expect(message.signature).to eq(sig2_b64)
end end