FEAL
APPENDIX FOR KATAGAITAI CTF TECHTALK
CSAW CTF 2014 QUALS - CRYPT0 300
YOU0708@YOKARO-MON
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
NOTICE
▸ This material is an appendix for katagaitai CTF TechTalk
▸ https://atnd.org/events/71810
▸ An modified version was used in katagaitai CTF
▸ Encryption key (SUBKEY) is fixed hex strings
FEAL 4.3
CSAW CTF 2014 QUALS
CRYPT0 300
FEAL
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
FEAL 4.3
▸ Feal 4.3 is used for the question
You must first solve a puzzle, a sha1 sum ending
in 16 bit's set to 1, it must be of length 21
bytes, starting with PkExU2wOJRG/XBDB
Welcome to feal 4.3
Please decrypt: edcf27af7821cc71615f329e78d1f65e
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
FBOX IN FEAL 4.3
▸ Feal 4.3 uses “rot 3” in fBox
▸ Differential values are not same with Feal 4
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
DIFFERENTIAL VALUE
In [1]: import array
In [2]: %paste
def rot3(x):
return ((x<<3)|(x>>5))&0xff
def gBox(a,b,mode):
return rot3((a+b+mode)%256)
def fBox(plain):
(snip.)
In [3]: x1 = array.array("B", "80800000".decode("hex"))
In [4]: fBox(x1)
Out[4]: [10, 64, 8, 68]
In [5]: x2 = array.array("B", "00000000".decode("hex"))
In [6]: fBox(x2)
Out[6]: [10, 64, 8, 64]
In [7]: for a, b in zip(fBox(x1), fBox(x2)):
print a ^ b,
....:
0 0 0 4 ΔY = 0x00000004
BREAKING
FEAL 4.3
CSAW CTF 2014 QUALS
CRYPT0 300
FEAL
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K3 FEALの最終ラウンドの差分解析49
0x02000000
key
f
出力差分(ΔC1)
ΔC1+ΔC2
入力差分(ΔX1) 入力差分(ΔX2)
出力差分(ΔC2)
f(C1+C2+key)+f(C1’+C2’+key)
この値は?
ΔC1 = f(C1+C2+key)+f(C1’+C2’+key)+0x02000000
0x00000004
0x00000004
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K3
k3 = None
if k3 == None:
print "[*] start k3 attack"
p1, p2, c1, c2, dc1, dc2, dcL, dcR = get_dataset(f, n,
array.array(“B”,"8080000080800000".decode("hex")))
for k3 in xrange(65536):
k3 = array.array("B", "%04x"%k3)
for i in xrange(n):
if dcL[i] != list_xor(
list_xor(
fBox(list_xor(dc1[i], k3)),
fBox(list_xor(dc2[i], k3))),
array("B", “00000004”.decode("hex"))
):
break
else:
print "[*] found k3: %s" % "".join(map(chr, k3))
break
else:
print "[!] could not find k3"
return
SUBKEY is hex string
Multiple candidates will be find
if you use few plainest sets
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K2
0x02000000
key
f
出力差分(ΔC1)
ΔC1+ΔC2
入力差分(ΔX1) 入力差分(ΔX2)
出力差分(ΔC2)
f(C1+C2+key)+f(C1’+C2’+key)
この値は?
ΔC1 = f(C1+C2+key)+f(C1’+C2’+key)+0x02000000
0x80800000
0x80800000
It can be calculated from
encrypted value and k3
It can be calculated from
encrypted value and k3
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K2
for i in xrange(n):
c1L = list_xor(c1[i][:4], c1[i][4:])
c1R = list_xor(c1[i][:4],
fBox(list_xor(k3, list_xor(c1[i][4:], c1[i][:4]))))
c2L = list_xor(c2[i][:4], c2[i][4:])
c2R = list_xor(c2[i][:4],
fBox(list_xor(k3, list_xor(c2[i][4:], c2[i][:4]))))
c1[i] = c1L + c1R
c2[i] = c2L + c2R
dcL[i] = list_xor(c1L, c2L)
for k2 in xrange(65536):
k2 = array.array("B", "%04x"%k2)
for i in xrange(n):
if dcL[i] != list_xor(
list_xor(
fBox(list_xor(c1[i][4:], k2)),
fBox(list_xor(c2[i][4:], k2))),
array("B", "80800000".decode("hex"))):
break
else:
print "[*] found k2: %s" % "".join(map(chr, k2))
break
else:
print "[!] could not find k2"
return
Calculate ΔC1, ΔC2 using k3
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K1
▸ You must re-generate plaintext sets to change result after
fBox
FEALの差分解析41
次の差分を持つ平文ペアを入力する
0x8080000080800000
同じ鍵で暗号化されているため鍵の入力差分は0
0x80800000 0x80800000
0x80800000
0
0x02000000
ここの差分は不明
0
ΔC1 is fixed value
It means: k1 can not be calculated
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K1
▸ e.g. ΔX = 0x0000000040000000
FEALの差分解析41
次の差分を持つ平文ペアを入力する
0x8080000080800000
同じ鍵で暗号化されているため鍵の入力差分は0
0x80800000 0x80800000
0x80800000
0
0x02000000
ここの差分は不明
0
0x00000000 0x40000000
0x40000000
????
????
ΔX1 = 0x40000000
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K1
0x02000000
key
f
出力差分(ΔC1)
ΔC1+ΔC2
入力差分(ΔX1) 入力差分(ΔX2)
出力差分(ΔC2)
f(C1+C2+key)+f(C1’+C2’+key)
この値は?
ΔC1 = f(C1+C2+key)+f(C1’+C2’+key)+0x02000000
0x40000000
0x40000000
It can be calculated from
encrypted value and k3
It can be calculated from
encrypted value, k3, and k2
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K1
p1, p2, c1, c2, dc1, dc2, dcL, dcR = get_dataset(f, n,
array.array("B","0000000040000000".decode("hex")))
for i in xrange(n):
c1L = list_xor(c1[i][:4], c1[i][4:])
c1R = list_xor(c1[i][:4],
fBox(list_xor(k3, list_xor(c1[i][4:], c1[i][:4]))))
c2L = list_xor(c2[i][:4], c2[i][4:])
c2R = list_xor(c2[i][:4],
fBox(list_xor(k3, list_xor(c2[i][4:], c2[i][:4]))))
c1[i] = c1L + c1R
c2[i] = c2L + c2R
dcL[i] = list_xor(c1L, c2L)
c1L = c1[i][4:]
c1R = list_xor(c1[i][:4], fBox(list_xor(k2, c1[i][4:])))
c2L = c2[i][4:]
c2R = list_xor(c2[i][:4], fBox(list_xor(k2, c2[i][4:])))
c1[i] = c1L + c1R
c2[i] = c2L + c2R
dcL[i] = list_xor(c1L, c2L)
for k1 in xrange(65536):
k1 = array.array("B", "%04x"%k1)
for i in xrange(n):
if dcL[i] != list_xor(
list_xor(
fBox(list_xor(c1[i][4:], k2)),
fBox(list_xor(c2[i][4:], k2))),
array("B", "80800000".decode("hex"))):
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K0
▸ e.g. ΔX = 0x0000000040000000
FEALの差分解析41
次の差分を持つ平文ペアを入力する
0x8080000080800000
同じ鍵で暗号化されているため鍵の入力差分は0
0x80800000 0x80800000
0x80800000
0
0x02000000
ここの差分は不明
0
0x00000000 0x40000000
0x0400000
????
????
ΔX1 = 0x00000000
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K0
for i in xrange(n):
c1L = c1[i][4:]
c1R = list_xor(c1[i][:4], fBox(list_xor(k1, c1[i][4:])))
c2L = c2[i][4:]
c2R = list_xor(c2[i][:4], fBox(list_xor(k1, c2[i][4:])))
c1[i] = c1L + c1R
c2[i] = c2L + c2R
dcL[i] = list_xor(c1L, c2L)
for k0 in xrange(65536):
k0 = array.array("B", "%04x"%k0)
for i in xrange(n):
if dcL[i] != list_xor(fBox(list_xor(c1[i][4:], k0)),
fBox(list_xor(c2[i][4:], k0))):
break
else:
print "[*] found k0: %s" % "".join(map(chr, k0))
break
else:
print "[!] could not find k0"
return
CSAW CTF 2014 QUALS - CRYPT0 300: FEAL
K4, K5, FLAG
k4 = list_xor(list_xor(fBox(list_xor(k0, c1[0][4:])),
c1[0][:4]),
p1[0][:4])
print "[*] found k4: %s" % "".join(map(chr, k4))
k5 = list_xor(list_xor(list_xor(p1[0][:4], k4), c1[0][4:]),
p1[0][4:])
print "[*] found k5: %s" % "".join(map(chr, k5))
k = [k0, k1, k2, k3, k4, k5]
print "[*] got encryption key:", k
flag = "".join(map(chr, feal.decrypt(array("B", flag1), k)))
+ "".join(map(chr, feal.decrypt(array("B", flag2), k)))
print "[*] the flag is:", flag
THANK YOU!
CSAW CTF 2014 QUALS
CRYPT0 300
FEAL

FEAL - CSAW CTF 2014 Quals Crypto300

  • 1.
    FEAL APPENDIX FOR KATAGAITAICTF TECHTALK CSAW CTF 2014 QUALS - CRYPT0 300 YOU0708@YOKARO-MON
  • 2.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL NOTICE ▸ This material is an appendix for katagaitai CTF TechTalk ▸ https://atnd.org/events/71810 ▸ An modified version was used in katagaitai CTF ▸ Encryption key (SUBKEY) is fixed hex strings
  • 3.
    FEAL 4.3 CSAW CTF2014 QUALS CRYPT0 300 FEAL
  • 4.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL FEAL 4.3 ▸ Feal 4.3 is used for the question You must first solve a puzzle, a sha1 sum ending in 16 bit's set to 1, it must be of length 21 bytes, starting with PkExU2wOJRG/XBDB Welcome to feal 4.3 Please decrypt: edcf27af7821cc71615f329e78d1f65e
  • 5.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL FBOX IN FEAL 4.3 ▸ Feal 4.3 uses “rot 3” in fBox ▸ Differential values are not same with Feal 4
  • 6.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL DIFFERENTIAL VALUE In [1]: import array In [2]: %paste def rot3(x): return ((x<<3)|(x>>5))&0xff def gBox(a,b,mode): return rot3((a+b+mode)%256) def fBox(plain): (snip.) In [3]: x1 = array.array("B", "80800000".decode("hex")) In [4]: fBox(x1) Out[4]: [10, 64, 8, 68] In [5]: x2 = array.array("B", "00000000".decode("hex")) In [6]: fBox(x2) Out[6]: [10, 64, 8, 64] In [7]: for a, b in zip(fBox(x1), fBox(x2)): print a ^ b, ....: 0 0 0 4 ΔY = 0x00000004
  • 7.
    BREAKING FEAL 4.3 CSAW CTF2014 QUALS CRYPT0 300 FEAL
  • 8.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K3 FEALの最終ラウンドの差分解析49 0x02000000 key f 出力差分(ΔC1) ΔC1+ΔC2 入力差分(ΔX1) 入力差分(ΔX2) 出力差分(ΔC2) f(C1+C2+key)+f(C1’+C2’+key) この値は? ΔC1 = f(C1+C2+key)+f(C1’+C2’+key)+0x02000000 0x00000004 0x00000004
  • 9.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K3 k3 = None if k3 == None: print "[*] start k3 attack" p1, p2, c1, c2, dc1, dc2, dcL, dcR = get_dataset(f, n, array.array(“B”,"8080000080800000".decode("hex"))) for k3 in xrange(65536): k3 = array.array("B", "%04x"%k3) for i in xrange(n): if dcL[i] != list_xor( list_xor( fBox(list_xor(dc1[i], k3)), fBox(list_xor(dc2[i], k3))), array("B", “00000004”.decode("hex")) ): break else: print "[*] found k3: %s" % "".join(map(chr, k3)) break else: print "[!] could not find k3" return SUBKEY is hex string Multiple candidates will be find if you use few plainest sets
  • 10.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K2 0x02000000 key f 出力差分(ΔC1) ΔC1+ΔC2 入力差分(ΔX1) 入力差分(ΔX2) 出力差分(ΔC2) f(C1+C2+key)+f(C1’+C2’+key) この値は? ΔC1 = f(C1+C2+key)+f(C1’+C2’+key)+0x02000000 0x80800000 0x80800000 It can be calculated from encrypted value and k3 It can be calculated from encrypted value and k3
  • 11.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K2 for i in xrange(n): c1L = list_xor(c1[i][:4], c1[i][4:]) c1R = list_xor(c1[i][:4], fBox(list_xor(k3, list_xor(c1[i][4:], c1[i][:4])))) c2L = list_xor(c2[i][:4], c2[i][4:]) c2R = list_xor(c2[i][:4], fBox(list_xor(k3, list_xor(c2[i][4:], c2[i][:4])))) c1[i] = c1L + c1R c2[i] = c2L + c2R dcL[i] = list_xor(c1L, c2L) for k2 in xrange(65536): k2 = array.array("B", "%04x"%k2) for i in xrange(n): if dcL[i] != list_xor( list_xor( fBox(list_xor(c1[i][4:], k2)), fBox(list_xor(c2[i][4:], k2))), array("B", "80800000".decode("hex"))): break else: print "[*] found k2: %s" % "".join(map(chr, k2)) break else: print "[!] could not find k2" return Calculate ΔC1, ΔC2 using k3
  • 12.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K1 ▸ You must re-generate plaintext sets to change result after fBox FEALの差分解析41 次の差分を持つ平文ペアを入力する 0x8080000080800000 同じ鍵で暗号化されているため鍵の入力差分は0 0x80800000 0x80800000 0x80800000 0 0x02000000 ここの差分は不明 0 ΔC1 is fixed value It means: k1 can not be calculated
  • 13.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K1 ▸ e.g. ΔX = 0x0000000040000000 FEALの差分解析41 次の差分を持つ平文ペアを入力する 0x8080000080800000 同じ鍵で暗号化されているため鍵の入力差分は0 0x80800000 0x80800000 0x80800000 0 0x02000000 ここの差分は不明 0 0x00000000 0x40000000 0x40000000 ???? ???? ΔX1 = 0x40000000
  • 14.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K1 0x02000000 key f 出力差分(ΔC1) ΔC1+ΔC2 入力差分(ΔX1) 入力差分(ΔX2) 出力差分(ΔC2) f(C1+C2+key)+f(C1’+C2’+key) この値は? ΔC1 = f(C1+C2+key)+f(C1’+C2’+key)+0x02000000 0x40000000 0x40000000 It can be calculated from encrypted value and k3 It can be calculated from encrypted value, k3, and k2
  • 15.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K1 p1, p2, c1, c2, dc1, dc2, dcL, dcR = get_dataset(f, n, array.array("B","0000000040000000".decode("hex"))) for i in xrange(n): c1L = list_xor(c1[i][:4], c1[i][4:]) c1R = list_xor(c1[i][:4], fBox(list_xor(k3, list_xor(c1[i][4:], c1[i][:4])))) c2L = list_xor(c2[i][:4], c2[i][4:]) c2R = list_xor(c2[i][:4], fBox(list_xor(k3, list_xor(c2[i][4:], c2[i][:4])))) c1[i] = c1L + c1R c2[i] = c2L + c2R dcL[i] = list_xor(c1L, c2L) c1L = c1[i][4:] c1R = list_xor(c1[i][:4], fBox(list_xor(k2, c1[i][4:]))) c2L = c2[i][4:] c2R = list_xor(c2[i][:4], fBox(list_xor(k2, c2[i][4:]))) c1[i] = c1L + c1R c2[i] = c2L + c2R dcL[i] = list_xor(c1L, c2L) for k1 in xrange(65536): k1 = array.array("B", "%04x"%k1) for i in xrange(n): if dcL[i] != list_xor( list_xor( fBox(list_xor(c1[i][4:], k2)), fBox(list_xor(c2[i][4:], k2))), array("B", "80800000".decode("hex"))):
  • 16.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K0 ▸ e.g. ΔX = 0x0000000040000000 FEALの差分解析41 次の差分を持つ平文ペアを入力する 0x8080000080800000 同じ鍵で暗号化されているため鍵の入力差分は0 0x80800000 0x80800000 0x80800000 0 0x02000000 ここの差分は不明 0 0x00000000 0x40000000 0x0400000 ???? ???? ΔX1 = 0x00000000
  • 17.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K0 for i in xrange(n): c1L = c1[i][4:] c1R = list_xor(c1[i][:4], fBox(list_xor(k1, c1[i][4:]))) c2L = c2[i][4:] c2R = list_xor(c2[i][:4], fBox(list_xor(k1, c2[i][4:]))) c1[i] = c1L + c1R c2[i] = c2L + c2R dcL[i] = list_xor(c1L, c2L) for k0 in xrange(65536): k0 = array.array("B", "%04x"%k0) for i in xrange(n): if dcL[i] != list_xor(fBox(list_xor(c1[i][4:], k0)), fBox(list_xor(c2[i][4:], k0))): break else: print "[*] found k0: %s" % "".join(map(chr, k0)) break else: print "[!] could not find k0" return
  • 18.
    CSAW CTF 2014QUALS - CRYPT0 300: FEAL K4, K5, FLAG k4 = list_xor(list_xor(fBox(list_xor(k0, c1[0][4:])), c1[0][:4]), p1[0][:4]) print "[*] found k4: %s" % "".join(map(chr, k4)) k5 = list_xor(list_xor(list_xor(p1[0][:4], k4), c1[0][4:]), p1[0][4:]) print "[*] found k5: %s" % "".join(map(chr, k5)) k = [k0, k1, k2, k3, k4, k5] print "[*] got encryption key:", k flag = "".join(map(chr, feal.decrypt(array("B", flag1), k))) + "".join(map(chr, feal.decrypt(array("B", flag2), k))) print "[*] the flag is:", flag
  • 19.
    THANK YOU! CSAW CTF2014 QUALS CRYPT0 300 FEAL