-
Notifications
You must be signed in to change notification settings - Fork 1
/
Program.fs
93 lines (79 loc) · 3.13 KB
/
Program.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Learn more about F# at http://fsharp.org
open System
open System.Security.Cryptography
open System.Threading
open System.Text
let sha = System.Security.Cryptography.SHA1.Create()
let getHash (input:string) =
sha.ComputeHash(Encoding.UTF8.GetBytes(input))
let seed =
()
//THIS COULD BE A USEFUL FUNCTION FOR DEBUGGIN
//THIS WILL PRINT THE BITS INSIDE YOUR ARRAY OF BYTES
// let bytesToBits (bytes:byte[]) =
// let bitMasks = Seq.unfold (fun bitIndex -> Some((byte(pown 2 bitIndex), bitIndex), bitIndex + 1)) 0
// |> Seq.take 8
// |> Seq.toList
// |> List.rev
// let byteToBitArray b = List.map (fun (bitMask, bitPosition) -> (b &&& bitMask) >>> bitPosition) bitMasks
// bytes
// |> Array.toList
// |> List.map byteToBitArray
// |> List.collect id
// |> List.toArray
let randomChars length =
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
let rand = System.Random()
let chars = String(Array.concat [ [|'A'..'Z'|]; [|'0'..'9'|]; [|'a'..'b'|] ])
String(Array.init length (fun _ -> chars.[rand.Next(chars.Length)]))
let mutable counter = 0
let header counter (randomString:string) =
let ver = sprintf "%i" 1
let bits = sprintf "%i" 20
let date = string (DateTime.Now.ToString("yyMMddmmss"))
let resource = "[email protected]"
let extension = String.Empty
let rand = Convert.ToBase64String(Encoding.UTF8.GetBytes(randomString))
let base64Counter = Convert.ToBase64String(Encoding.UTF8.GetBytes(string counter))
sprintf "%s:%s:%s:%s:%s:%s:%s" ver bits date resource extension rand base64Counter
let checkHash (hash:byte[]) =
let firstByte = (hash.[0] = byte 0)
let secondByte = (hash.[1] = byte 0)
let thirdByte = (hash.[2] <= byte 15)
firstByte && secondByte && thirdByte
let compute index randomString =
let hash = getHash (header index randomString)
if not <| checkHash hash
then
false
else
counter <- index
true
let verify header =
let hash = getHash header
checkHash hash
let sender () =
let continueTaking result =
not <| result
let randomString = randomChars 8
Seq.initInfinite (fun index -> index + 1)
|> Seq.takeWhile (fun index -> (continueTaking (compute index randomString)
&& index < 2000000)) //limit so it does not run forever just in case. this should find a solution on average in 2^20 tries
|> Seq.iter ignore
printfn "FINAL COUNT %i " counter
printfn "HASH %s" (header counter randomString)
()
let recipient header =
printfn "does it pass? %A" (verify header)
()
[<EntryPoint>]
let main argv =
printfn "STARTING HASHCASH F#"
printfn "%A" DateTime.Now
match argv.[0] with
| "sender" -> sender ()
| "recipient" -> printfn "%s" argv.[1]
recipient argv.[1]
| _ -> printfn "%s" "Argument not allowed."
printfn "%A" DateTime.Now
0 // return an integer exit code