导引章

关于

本系列当前主要是 Rratic 的 the cryptopals crypto challenges 游玩笔记(分享性的)。

根据词典

crypto- Modern Latin Greek kryptos “hidden”, from kryptein “to hide”

而“cryptopals”似乎在词典中查不到。

Set 1 说明

beat oneself up v. 自责

1-1

根据给出的建议

Always operate on raw bytes, never on encoded strings. Only use hex and base64 for pretty-printing.

先写一些实用函数

function getint(arr::BitArray, itr, type::Type{T} where T <: Integer = UInt8)
	num = zero(type)
	for i in itr
		num <<= 1
		if arr[i]
			num += one(type)
		end
	end
	num
end
function setint!(arr::BitArray, itr, num::Integer)
	for i in reverse(itr)
		arr[i] = Bool(num&0x1)
		num >>= 1
	end
end

写对应的功能。按照语境,出现的所有字符都应是标准 ASCII 中的,故暂时不必进行 Unicode(完全)兼容。

function hex2bitarr(hexstr)
	arr = BitArray(undef, sizeof(hexstr)*4)
	@inbounds for i in 1:sizeof(hexstr)
		u8_ch = UInt8(hexstr[i])
		n = u8_ch <= 0x39 ?
			u8_ch - 0x30 :
			u8_ch - 0x61 + 0xa
		setint!(arr, i*4-3:i*4, n)
	end
	arr
end

Base64

function base64unitencode(u8)
	u8 <= 25 ? 'A' + u8 :
	u8 <= 51 ? 'a' + u8 - 26 :
	u8 <= 61 ? '0' + u8 - 52 :
	u8 == 62 ? '+' : '/'
end
function bitarr2base64(arr)
	n, r = divrem(length(arr), 6)
	str = ""
	@inbounds for i in 1:n
		u8_64 = getint(arr, i*6-5:i*6, UInt8)
		str *= base64unitencode(u8_64)
	end
	if !iszero(r)
		u8_64 = getint(arr, n*6+1:length(arr), UInt8) <<
			(6-r)
		str *=  base64unitencode(u8_64)
	end
	m4 = sizeof(str) % 4
	iszero(m4) || (str *= '='^(4-m4))
	str
end

主流程:

function main()
	readline(stdin) |> hex2bitarr |> bitarr2base64 |> println
end