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 }