在博客上实施 ID 加密不会产生相同的输出
我看到这篇博客文章,其中描述了他们如何加密他们的 ID。出于教育和娱乐目的,我决定尝试一下。但我不太明白。
正如这篇博文中所述,我是基础36 对 3DES 加密的 64 位填充值进行编码,并保持结果字符串的长度为 25 个字符。如何在不使用流密码的情况下获得 13 个字符(如该网站声称的那样)——该博客声称使用 3DES 分组密码。
这是我正在使用的代码:
require 'openssl'
SECRET_KEY = "secret"
ENCRYPTION_ALGO = "DES-EDE3-CBC"
def base36encode(s)
s.unpack('H*')[0].to_i(16).to_s 36
end
def base36decode(s36)
[s36.to_i(36).to_s(16)].pack 'H*'
end
def num_to_bits(n, bit_count=64)
#Array.new(bit_count) { |i| (n)[i] }.reverse!
sprintf('%064b', n).split("")
end
def bits_to_string(bits)
[bits.join("")].pack("B*")
end
def num_to_binstring(n, bit_count=64)
bits_to_string(num_to_bits(n, bit_count))
end
def binstring_to_num(str)
#elements = str.unpack("N*")
#(elements[0] << 32) | elements[1]
#
ans = 0
str.each_byte do |i|
ans = ans * 256 + i
end
ans
end
def encrypt(message, password)
cipher = OpenSSL::Cipher::Cipher.new(ENCRYPTION_ALGO)
cipher.encrypt
cipher.pkcs5_keyivgen(password)
ciphertext = cipher.update(message)
ciphertext << cipher.final
end
def decrypt(message, password)
cipher = OpenSSL::Cipher::Cipher.new(ENCRYPTION_ALGO)
cipher.decrypt
cipher.pkcs5_keyivgen(password)
decryptedtext = cipher.update(message)
decryptedtext << cipher.final
end
id = 12345678
puts "Encrypting: \"#{id}\""
num_string = num_to_binstring(id)
encrypted = encrypt(num_string, SECRET_KEY)
encoded = base36encode(encrypted).upcase
puts "Encrypted and encoded to: \"#{encoded}\" that's size is: #{encoded.length}\n"
decoded = base36decode(encoded.downcase)
decrypted = decrypt(decoded, SECRET_KEY)
string_num = binstring_to_num(decrypted)
puts "Decoded and decrypted to: \"#{string_num}\""
# ---- OUTPUT ---
# Encrypting: "12345678"
# Encrypted and encoded to: "49OMDVRHHMM24DVMODQU4X7JY" that's size is: 25
# Decoded and decrypted to: "12345678"
I came across this blog post which describes how they encrypt their ID's. For educational and entertainment purposes, I decided to try this out. I can't quite get it, though.
As described in this blog post, I'm base 36 encoding the 3DES encrypted 64 bit padded value and keep getting the resulting string to be 25 characters long. How is it possible to get 13 characters, like the site claims, without using some stream cipher -- the blog claims to use a 3DES block cipher.
Here's the code I'm using:
require 'openssl'
SECRET_KEY = "secret"
ENCRYPTION_ALGO = "DES-EDE3-CBC"
def base36encode(s)
s.unpack('H*')[0].to_i(16).to_s 36
end
def base36decode(s36)
[s36.to_i(36).to_s(16)].pack 'H*'
end
def num_to_bits(n, bit_count=64)
#Array.new(bit_count) { |i| (n)[i] }.reverse!
sprintf('%064b', n).split("")
end
def bits_to_string(bits)
[bits.join("")].pack("B*")
end
def num_to_binstring(n, bit_count=64)
bits_to_string(num_to_bits(n, bit_count))
end
def binstring_to_num(str)
#elements = str.unpack("N*")
#(elements[0] << 32) | elements[1]
#
ans = 0
str.each_byte do |i|
ans = ans * 256 + i
end
ans
end
def encrypt(message, password)
cipher = OpenSSL::Cipher::Cipher.new(ENCRYPTION_ALGO)
cipher.encrypt
cipher.pkcs5_keyivgen(password)
ciphertext = cipher.update(message)
ciphertext << cipher.final
end
def decrypt(message, password)
cipher = OpenSSL::Cipher::Cipher.new(ENCRYPTION_ALGO)
cipher.decrypt
cipher.pkcs5_keyivgen(password)
decryptedtext = cipher.update(message)
decryptedtext << cipher.final
end
id = 12345678
puts "Encrypting: \"#{id}\""
num_string = num_to_binstring(id)
encrypted = encrypt(num_string, SECRET_KEY)
encoded = base36encode(encrypted).upcase
puts "Encrypted and encoded to: \"#{encoded}\" that's size is: #{encoded.length}\n"
decoded = base36decode(encoded.downcase)
decrypted = decrypt(decoded, SECRET_KEY)
string_num = binstring_to_num(decrypted)
puts "Decoded and decrypted to: \"#{string_num}\""
# ---- OUTPUT ---
# Encrypting: "12345678"
# Encrypted and encoded to: "49OMDVRHHMM24DVMODQU4X7JY" that's size is: 25
# Decoded and decrypted to: "12345678"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在进行 Base36 编码之前,加密输出的大小是多少?我的猜测是,您的代码正在 CBC 模式下加密(假设您的代码提到了 pkcs5),并且您正在获取 IV 和密文,总共 16 个字节。我从博客文章中推断,作者使用的是 ECB 模式,您可能会认为“原始”3DES,这在大多数情况下通常是错误的,但在这里似乎是合理的。
What size is the output of the encryption before you base36 encode? My guess is that your code is encrypting in CBC mode (given that your code mentions pkcs5) and you're getting the IV and ciphertext out, a total of 16 bytes. I infer from the blog post that the author is using ECB mode, what you might think of as "raw" 3DES, which is usually wrong for most situations but seems plausible here.