AES key — encoded in the machine readable zone of a European ePassport
AES key
— encoded in the machine readable zone of a European ePassport
题目地址
AES key — encoded in the machine readable zone of a European ePassport
解题过程
第一步:补全给出的密钥
通过查阅题目附录里提到的文档,可以找到校验位的具体机制,依据解释可求出初始密钥"?"处的取值
def pre(k):
k = list(k)
weights = [7, 3, 1, 7, 3, 1]
sum = 0
for i in range(21, 27):
sum += int(k[i]) * weights[i - 21]
sum %= 10
k[27] = str(sum)
return ''.join(k)
第二步:根据文档对\(K_{seed}\)的描述还原MRZ_information和\(K_{seed}\)
def getK_seed(k):
mrz_imt = k[:10] + k[13:20] + k[21:28]
H_SHA1 = sha1(mrz_imt.encode()).hexdigest()
return H_SHA1[:32]
第三步:根据附录五求出\(K_{ENC}\),也就是Key
由于我们只需要求出\(K_{ENC}\),所以只需要令c='00000001'即可
def getKab(k):
kab = []
k = '{:064b}'.format(int(k, 16))
for i in range(0, len(k), 8):
kab.append(k[i:i + 7])
if k[i:i + 7].count('1') % 2 == 0:
kab.append('1')
else:
kab.append('0')
return hex(int(''.join(kab), 2))[2:]
def getKey(k):
k = k + '00000001'
H = sha1(bytes.fromhex(k)).hexdigest()
return getKab(H[:16]) + getKab(H[16:32])
第四步:利用求得的Key求出明文
用CBC模式下的AES加密即可直接求出密文
def getP(C, k):
C = b64decode(C)
aes = AES.new(bytes.fromhex(k), AES.MODE_CBC, bytes.fromhex('0'*32))
return aes.decrypt(C).decode()
运行结果
完整代码
from hashlib import sha1
from base64 import b64decode
from Crypto.Cipher import AES
C = '9MgYwmuPrjiecPMx61O6zIuy3MtIXQQ0E59T3xB6u0Gyf1gYs2i3K9Jxaa0zj4gTMazJuApwd6+jdyeI5iGHvhQyDHGVlAuYTgJrbFDrfB22Fpil2NfNnWFBTXyf7SDI'
K = '12345678<8<<<1110182<111116?<<<<<<<<<<<<<<<4'
def pre(k):
k = list(k)
weights = [7, 3, 1, 7, 3, 1]
sum = 0
for i in range(21, 27):
sum = (sum + int(k[i]) * weights[i - 21]) % 10
k[27] = str(sum)
return ''.join(k)
def getK_seed(k):
mrz_imt = k[:10] + k[13:20] + k[21:28]
H_SHA1 = sha1(mrz_imt.encode()).hexdigest()
return H_SHA1[:32]
def getKab(k):
kab = []
k = '{:064b}'.format(int(k, 16))
for i in range(0, len(k), 8):
kab.append(k[i:i + 7])
if k[i:i + 7].count('1') % 2 == 0:
kab.append('1')
else:
kab.append('0')
return hex(int(''.join(kab), 2))[2:]
def getKey(k):
k = k + '00000001'
H = sha1(bytes.fromhex(k)).hexdigest()
return getKab(H[:16]) + getKab(H[16:32])
def getP(C, k):
C = b64decode(C)
aes = AES.new(bytes.fromhex(k), AES.MODE_CBC, bytes.fromhex('0'*32))
return aes.decrypt(C).decode()
if __name__ == '__main__':
K = pre(K)
K_seed = getK_seed(K)
Key = getKey(K_seed)
P = getP(C, Key)
print(P)
感想
对加密方式有了更新的认识,通过设置多个且校验方式不同的校验位进行检验的方式很有趣。这个题目的实现代码不长,但基于飞行护照的背景,也让我认识深刻:密码在生活中,无处不在。