mit-ocw

Source code for MIT-OCW coursework
git clone git://git.laack.co/mit-ocw.git
Log | Files | Refs

main.go (3653B)


      1 package main
      2 
      3 import (
      4     "github.com/google/uuid"
      5 	"bytes"
      6 	"crypto/sha256"
      7 	"encoding/hex"
      8 	"fmt"
      9 	"strings"
     10 )
     11 
     12 type knownBitSt struct {
     13 	firstPair [256]bool
     14 	secondPair [256]bool
     15 }
     16 
     17 
     18 func knownBits(publicKey Key, signature string, known knownBitSt, knownPrivate Key) (knownBitSt, Key){
     19 
     20 	signatureBytes, err := hex.DecodeString(signature)
     21 
     22 	if err != nil {
     23 		panic(err)
     24 	}
     25 
     26 	for i := 0; i < 256; i++ {
     27 
     28 		hash := sha256.Sum256(signatureBytes[i*32:i*32 + 32][:])
     29 
     30 		if bytes.Compare(publicKey.firstRow[i][:], hash[:]) == 0 {
     31 			known.firstPair[i] = true
     32 			copy(knownPrivate.firstRow[i][:], signatureBytes[i*32:i*32 + 32][:])
     33 		} else {
     34 
     35 			if bytes.Compare(publicKey.secondRow[i][:], hash[:]) != 0 {
     36 				panic("Malformed signature")
     37 			}
     38 
     39 			known.secondPair[i] = true
     40 			copy(knownPrivate.secondRow[i][:], signatureBytes[i*32:i*32 + 32][:])
     41 		}
     42 	}
     43 
     44 	return known, knownPrivate
     45 }
     46 
     47 func stringToKey(key string) Key {
     48 
     49 	returnKey := Key{}
     50 
     51 	pkeyHex, err := hex.DecodeString(key)
     52 
     53 	if err != nil {
     54 		panic(err)
     55 	}
     56 
     57 	for idx := 0 ; idx < 256; idx++ {
     58 		copy(returnKey.firstRow[idx][:], pkeyHex[idx*32:(idx*32)+32])
     59 	}
     60 	for idx := 0 ; idx < 256; idx++ {
     61 		copy(returnKey.secondRow[idx][:], pkeyHex[idx*32 + 256*32:(idx*32)+32 + 256*32])
     62 	}
     63 
     64 
     65 	return returnKey
     66 }
     67 
     68 func keyToHexString(key Key) string {
     69 	result := ""
     70 	for i := 0; i < 256; i++ {
     71 		result += hex.EncodeToString(key.firstRow[i][:])
     72 	}
     73 	for i := 0; i < 256; i++ {
     74 		result += hex.EncodeToString(key.secondRow[i][:])
     75 	}
     76 	return result
     77 }
     78 
     79 func countKnown(known knownBitSt) int {
     80 	count := 0
     81 
     82 	for _, val := range known.firstPair {
     83 		if val {
     84 			count += 1
     85 		}
     86 	}
     87 	for _, val := range known.secondPair {
     88 		if val {
     89 			count += 1
     90 		}
     91 	}
     92 	return count
     93 }
     94 
     95 
     96 func genAndCheck(testStr string, known knownBitSt) string {
     97 
     98 	messageHash := sha256.Sum256([]byte(testStr))
     99 	
    100 	for index, _ := range messageHash {
    101 		currentByteString := fmt.Sprintf("%08b", messageHash[index])
    102 		for bitId, bit := range currentByteString {
    103 			if bit == '0' {
    104 				if !known.firstPair[index*8 + bitId] {
    105 					return ""
    106 				}
    107 			} else {
    108 				if !known.secondPair[index*8 + bitId] {
    109 					return ""
    110 				}
    111 			}
    112 		}
    113 	}
    114 
    115 	return testStr
    116 }
    117 
    118 
    119 func main() {
    120 
    121 	pubKey := stringToKey(hexPubkey1)
    122 
    123 	validation := true
    124 
    125 	// validate encode / decode invariant
    126 	if validation {
    127 		decoded := keyToHexString(pubKey)
    128 		if strings.Compare(decoded, hexPubkey1) != 0 {
    129 			fmt.Println("Encoding / decoding key didn't work correctly...")
    130 			fmt.Printf("Original: %s\nNew: %s\n", hexPubkey1, decoded)
    131 		}
    132 	}
    133 
    134 	
    135 	known := knownBitSt{}
    136 	knownPrivate := Key{}
    137 
    138 	known, knownPrivate = knownBits(pubKey, hexSignature1, known, knownPrivate)
    139 	known, knownPrivate = knownBits(pubKey, hexSignature2, known, knownPrivate)
    140 	known, knownPrivate = knownBits(pubKey, hexSignature3, known, knownPrivate)
    141 	known, knownPrivate = knownBits(pubKey, hexSignature4, known, knownPrivate)
    142 
    143 	fmt.Println("Known: ", countKnown(known))
    144 
    145 	prefix := "forge - andrew laack - andrew@laack.co - "
    146 
    147 	found := false
    148 	final := ""
    149 
    150 	// TODO: good idea to parallelize this...
    151 	for !found {
    152 
    153 		testStr := prefix + uuid.New().String()
    154 		
    155 		result := genAndCheck(testStr,known)
    156 		if strings.Compare(result, "") != 0 {
    157 			found = true
    158 			final = result
    159 		}
    160 	}
    161 
    162 
    163 	finResult := Sign(knownPrivate, final)
    164 
    165 	byteSequence := []byte{}
    166 
    167 	for _, val := range finResult {
    168 		byteSequence = append(byteSequence, val[:]...)
    169 	}
    170 
    171 	fmt.Printf("Signature: %s\n", hex.EncodeToString(byteSequence))
    172 	fmt.Printf("Message: %s\n", final)
    173 
    174 
    175 	matches := Verify(pubKey, final, finResult)
    176 	fmt.Printf("This signature matches the message and public key: %v\n", matches)
    177 
    178 	// See forged.txt for an instance I found.
    179 
    180 }