ruby base64 encode 128 bit number by starting with a 2 bit character to prevent padding at the end

本小妞迷上赌 提交于 2019-12-10 23:01:36

问题


This question is a follow up to my previous question here: How can I convert a UUID to a string using a custom character set in Ruby? But I will try to formulate it as a separate and specific question.

I do have a Ruby 128 bit UUID as hex value:

SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"

If I get the IFC specification correctly (http://www.buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcutilityresource/lexical/ifcgloballyuniqueid.htm), I want to Base64 encode this, but instead of getting padding at the end, I want the output to begin with a 2bit character(4 options), instead of 6 bits(needed for 64 options).

This way I think I can end up with a string of 22 characters (1 of 2bits, and 21 of 6bits for a total of 128 bits).

Is it possible to tweak the Ruby base64 in this way?


回答1:


Short answer: no. Technically speaking, that is not standard Base64 so Ruby's standard lib will not deal with it.

Ruby's Base64 lib takes its input as bytes, so you need to get your input data to be divisible by 8. But you want 4 zero bits in front of your UUID, so that's 4+128=132 so the next closest multiple of 8 is 136 i.e. 17 bytes. You can discard the extra randomness at the end:

x = SecureRandom.gen_random 17   # get a little extra randomness
x[0] = (x[0].ord & 0x0f).chr     # 0 out the first four bits
Base64.strict_encode64(x)[0...22] # discard extra randomness

The one downside of this approach is that your 128 bit UUID is weirdly aligned inside x and hard to see on its own. If you want to get the 128 bits out you can do that with some pack/unpack:

[x.unpack("B*")[0][4...132]].pack("B*")


来源:https://stackoverflow.com/questions/47839720/ruby-base64-encode-128-bit-number-by-starting-with-a-2-bit-character-to-prevent

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!