首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >字符串的Base62哈希

字符串的Base62哈希
EN

Stack Overflow用户
提问于 2014-05-28 21:58:36
回答 1查看 11.3K关注 0票数 7

我想做一些像fingerprint = Digest::SHA256.base64digest(str)这样的事情,但是为了base62而不是base64。如何有效地为任何字符串构建一个惟一的base62编码的字符串散列?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-28 22:57:00

Base64被广泛用于编码二进制数据,因为6位恰好适合一个字符,但仍然有足够的可打印ASCII字符来表示所有可能的模式。换句话说,64个可用字符代表从十进制0到十进制63的所有64种不同的位模式。

将二进制数据编码为基数62有几个问题,这是基于这样一个事实,即62大小的字母表并不适合。您可以将摘要算法中的二进制数据映射到32位块中,然后将这些5位块中的每一个分配给一个字符。然而,这意味着"v“上面的字符将不再被使用,因此您实际上将最终使用base32编码。

在效率方面,base 62永远不会,甚至不会接近base64。Base64编码非常简单:取6位,将它们映射到一个字符上,重复直到完成。这很简单,因为64是2的幂。然而,使用基数62,你将不得不转换成一个整数,并开始在每一步中传递“余数”,因为模式并不均匀。

因此,我的建议(您可能不喜欢)是使用不同的编码。

--

如果你需要一个url安全的编码,你可以使用下面的方法之一:

代码语言:javascript
运行
复制
# sample string
str = 'foo'

# original base 64 method for comparison
Digest::SHA256.base64digest(str)
#=> "LCa0a2j/xo/5m0U8HTBBNBNCLXBkg7+g+YpeiGJm564="

# url safe variant (no slash or plus characters)
Base64.urlsafe_encode64(Digest::SHA256.digest(str))
#=> "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564="

# hexadecimal (base 16)
Digest::SHA256.hexdigest(str)
#=> "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"

# or base 32
# gem install base32
require 'base32'
Base32.encode(Digest::SHA256.digest(str))
#=> "FQTLI23I77DI76M3IU6B2MCBGQJUELLQMSB37IHZRJPIQYTG46XA===="

# or with direct url encoding
# not pretty, but url safe!
require 'open-uri'
URI::encode(Digest::SHA256.digest(str))
#=> ",&%B4kh%FF%C6%8F%F9%9BE%3C%1D0A4%13B-pd%83%BF%A0%F9%8A%5E%88bf%E7%AE"

# or url url escaped base 64
# not pretty, but url safe!
require 'cgi'
CGI::escape(Digest::SHA256.base64digest(str))
#=> "LCa0a2j%2Fxo%2F5m0U8HTBBNBNCLXBkg7%2Bg%2BYpeiGJm564%3D"

--

编辑:这是一个非常低效的base62实现;-)

代码语言:javascript
运行
复制
# gem install 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"

# encode
digest = Digest::SHA256.digest(str)
fingerprint = base62_encode(digest)
#=> "fTSIMrZT3fDTvW7XDBq1b7nhWa24Zl55EVpsaO3TBBE"

# decode
recovered_digest = base62_decode(fingerprint)
#=> ",&\xB4kh\xFF\xC6\x8F\xF9\x9BE<\x1D0A4\x13B-pd\x83\xBF\xA0\xF9\x8A^\x88bf\xE7\xAE"

digest == recovered_digest
#=> true
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23913737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档