Base 64 is widely used for encoding binary data, because 6 bits correspond exactly to one character, but there are still enough printable ASCII characters to represent all possible patterns. In other words, 64 available characters represent all 64 different bit patterns from decimal from 0 to decimal 63.
There are several problems with encoding binary data as base 62, based on the fact that an alphabet of size 62 just doesn't fit. You can simply map the binary data from the digest algorithm into 32-bit chunks, and then assign each of these 5-bit fragments to a character. However, this means that the characters above "v" will no longer be used, so you will essentially get the base 32 encoding.
In terms of efficiency, base 62 will never even come close to base64. Base 64 encoding is dead simple: take 6 bits, draw them on a character, repeat to the end. It is so simple because 64 is power 2. With base 62, however, you will need to convert to an integer and start transferring the “remainder” with each step, because the patterns do not fit evenly.
, , , .
-
url, , , :
str = 'foo'
Digest::SHA256.base64digest(str)
Base64.urlsafe_encode64(Digest::SHA256.digest(str))
Digest::SHA256.hexdigest(str)
require 'base32'
Base32.encode(Digest::SHA256.digest(str))
require 'open-uri'
URI::encode(Digest::SHA256.digest(str))
require 'cgi'
CGI::escape(Digest::SHA256.base64digest(str))
-
: base62; -)
require 'base62'
def pack_int(str)
str.unpack('C*').each_with_index.reduce(0){|r,(x,i)| r + (x << 8*i) }
end
def unpack_int(int)
n = (Math.log2(int)/8).ceil
n.times.map{|i| (int >> 8*i) & 255 }.pack('C*')
end
def base62_encode(str)
Base62.encode(pack_int(str))
end
def base62_decode(encoded)
unpack_int(Base62.decode(encoded))
end
str = "foo"
digest = Digest::SHA256.digest(str)
fingerprint = base62_encode(digest)
recovered_digest = base62_decode(fingerprint)
digest == recovered_digest