2

これは、Python で実装したい Ruby の一部です。

Base64.urlsafe_encode64([Digest::MD5.hexdigest(url).to_i(16)].pack("N")).sub(/==\n?$/, '')

おわかりのように、これは URL を次のように変えるのに役立ちます。

http://stackoverflow.com/questions/ask

thise のような小さなコードに:

sUEBtw

プロセスで生成される大きな整数は次のとおりです。

307275247029202263937236026733300351415

この Python コードを使用して、これをバイナリ形式にパックすることができました。

url = 'http://stackoverflow.com/questions/ask'
n = int(hashlib.md5(url).hexdigest(), 16)                                       
s = struct.Struct('d')                                                          
values = [n]                                                                    
packed_data = s.pack(*values)                                                   
short_code = base64.urlsafe_b64encode(packed_data)[:-1]
print short_code

私が得る短いコードはこれです:

zgMM62Hl7Ec

ご覧のとおり、Ruby で取得したものよりも大きくなっています。これは、パッキングが別の形式を使用しているためです。

あなたの助けをいただければ幸いです。

4

3 に答える 3

2

これはトリックを行います:

import hashlib
import base64
url = 'http://stackoverflow.com/questions/ask'
print base64.urlsafe_b64encode(hashlib.md5(url).digest()[-4:])[:-2]

出力

sUEBtw

.digest()完全な 16 バイトのダイジェストのパックされたバイトを提供するので、必要はありませんがstruct.pack、Ruby.pack('N')はダイジェストの最後の 4 バイトのみを変換するようです。

于 2012-04-02T03:02:30.673 に答える
1

Rubypack('N')はネットワーク順序 (ビッグエンディアン) 32 ビット符号なしに変換します。pythonstruct('d')は、IEEE 倍精度浮動小数点数に変換します。struct('>I')同等のビッグエンディアン 32 ビット unsigned in pythonが必要だと思います。

于 2012-04-02T02:43:18.140 に答える
0

pack('N')したがって、Rubyは下位 4 バイトのみを使用することが明らかになったため、 DSMの提案に従って、次のコードを機能させました。

import hashlib
import base64

url = 'https://stackoverflow.com/questions/ask'
n = int(hashlib.md5(url).hexdigest(), 16)                                       
s = struct.Struct('>I')                                                         
values = [n % (2**32)]                                                          
packed_data = s.pack(*values)                                                   
print base64.urlsafe_b64encode(packed_data)[:-2] 

それにもかかわらず、 Mark Tolonenの回答で説明されているように、hashlibの HASH オブジェクトのメソッドでは、ハッシュが既にパックされているため、 を使用してエンコードするためdigest()に最後の 4 バイトを取得するだけで十分です。[-4:]Base64urlsafe_b64encode

于 2012-04-02T04:52:02.493 に答える