Simple DFA on SM4 round31, round30, round29 and round 28.
And recover the master key by these four round keys.
Ref:
Ruilin Li, Bing Sun, Chao Li, Jianxiong You, Differential Fault Analysis on SMS4 using a single fault, Information Processing Letters, Volume 111, Issue 4, 2011, Pages 156-163, ISSN 0020-0190,
https://doi.org/10.1016/j.ipl.2010.11.011.
张蕾,吴文玲.SMS4密码算法的差分故障攻击[J].计算机学报,2006(09):1596-1602.
Script should be run under python3.
test function:
def foo():
masterKey = b'\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10'
in_put = b'\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10'
# last_round_key = [k31, k30, k29, k28]
#last_round_key = [0x9124a012, 0x01cf72e5 ,0x62293496, 0x428d3654]
sk = set_key(masterKey, SM4_ENCRYPT)
#print("fault output:")
r31 = [gen_fault_cipher(in_put, sk, 31) for i in range(30)]
r30 = [gen_fault_cipher(in_put, sk, 30) for i in range(30)]
r29 = [gen_fault_cipher(in_put, sk, 29) for i in range(30)]
r28 = [gen_fault_cipher(in_put, sk, 28) for i in range(30)]
ref = sm4_encrypt(in_put, sk)
last_round_key = []
key_schedule = []
last_round_key.append(crack_round(r31,ref))
last_round_key.append(crack_round(r30,ref,last_round_key))
last_round_key.append(crack_round(r29,ref,last_round_key))
last_round_key.append(crack_round(r28,ref,last_round_key))
key_schedule = recovery_key(last_round_key)
MK = get_masterKey(key_schedule)
dump_byte(MK)
Faulty ciphers are generated by gen_fault_cipher()
Also, you can get the faulty cipher from other sources.
Run the script:
python3 ./sm4_dfa.py
Result:
Master Key found:
/x01/x23/x45/x67/x89/xab/xcd/xef/xfe/xdc/xba/x98/x76/x54/x32/x10