From 3b0fb163cbac08a36b01f186b72e2a9cee4b7a2d Mon Sep 17 00:00:00 2001 From: rsiddharth Date: Sat, 29 Aug 2020 20:00:53 -0400 Subject: challenge: do challenge 3 * challenge/c03.go: Implement challenge 3 * cryptopals.go (main): Add handling to run challenge 3 * lib/brute.go (XORCrackSingleKey): New function. * lib/hex.go (HexStrToAsciiStr, ByteToHexStr): New functions. * lib/str.go (FillStr): New function. --- challenge/c03.go | 17 +++++++++++++++++ cryptopals.go | 2 ++ lib/brute.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/hex.go | 29 +++++++++++++++++++++++++++++ lib/str.go | 15 +++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 challenge/c03.go create mode 100644 lib/brute.go create mode 100644 lib/str.go diff --git a/challenge/c03.go b/challenge/c03.go new file mode 100644 index 0000000..019aaff --- /dev/null +++ b/challenge/c03.go @@ -0,0 +1,17 @@ +// Copyright © 2020 rsiddharth +// SPDX-License-Identifier: ISC + +package challenge + +import ( + "fmt" + "ricketyspace.net/cryptopals/lib" +) + +func C3() { + hs := "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736" + k, ds, scr := lib.XORCrackSingleKey(hs) + + fmt.Printf("Key is '%c' (Score: %v)\n", k, scr) + fmt.Printf("Decrypted string: %v\n", ds) +} diff --git a/cryptopals.go b/cryptopals.go index 37580be..5faa363 100644 --- a/cryptopals.go +++ b/cryptopals.go @@ -22,5 +22,7 @@ func main() { challenge.C1() case 2: challenge.C2() + case 3: + challenge.C3() } } diff --git a/lib/brute.go b/lib/brute.go new file mode 100644 index 0000000..54be06b --- /dev/null +++ b/lib/brute.go @@ -0,0 +1,56 @@ +// Copyright © 2020 rsiddharth +// SPDX-License-Identifier: ISC + +package lib + +// Average Word Length (English). +const awl float64 = 4.7 + +// 'hs' must be a hex encoded string. +func XORCrackSingleKey(hs string) (byte, string, float64) { + l := len(hs) / 2 + + var k byte = 0 + var ds string = "" + var scr float64 = 100.0 + + i := byte(0) + for i < 255 { + ks := FillStr(ByteToHexStr(i), l) + xs := FixedXOR(hs, ks) + as := HexStrToAsciiStr(xs) + + s := phraseScore(as) + if s < scr { + k = i + ds = as + scr = s + } + i += 1 + } + return k, ds, scr +} + +func phraseScore(phrase string) float64 { + pl := len(phrase) + + // Expected number of words. + ew := float64(pl) / awl + + // Number of words in phrase. + ws := 0.0 + + for i := 0; i < pl; i++ { + if phrase[i] == ' ' { + ws += 1.0 + } + } + ws += 1.0 + + // Compute score. + score := 1.0 - (ws / ew) + if score < 0 { + score *= -1 + } + return score +} diff --git a/lib/hex.go b/lib/hex.go index bf539bc..6fe7e6a 100644 --- a/lib/hex.go +++ b/lib/hex.go @@ -24,3 +24,32 @@ func DecToHexChar(i uint16) byte { } return 0 } + +// 'h' must be hex encoded string. +func HexStrToAsciiStr(h string) string { + a := "" + lh := len(h) + + if lh < 1 { + return a + } + if lh == 1 { + return string(HexCharToDec(h[0])) + } + + for i := 0; i < lh; i += 2 { + b := HexCharToDec(h[i])<<4 | HexCharToDec(h[i+1]) + a += string(b) + } + return a +} + +func ByteToHexStr(b byte) string { + p := DecToHexChar(uint16(b >> 4)) + q := DecToHexChar(uint16(b & 0xf)) + + s := string(p) + s += string(q) + + return s +} diff --git a/lib/str.go b/lib/str.go new file mode 100644 index 0000000..e0cb8ae --- /dev/null +++ b/lib/str.go @@ -0,0 +1,15 @@ +// Copyright © 2020 rsiddharth +// SPDX-License-Identifier: ISC + +package lib + +func FillStr(a string, l int) string { + b := "" + if l < 1 { + return b + } + for i := 0; i < l; i++ { + b += a + } + return b +} -- cgit v1.2.3