3 people like it.
Like the snippet!
TOTP - Time Based One Time Password
Generate timebased one time passwords, for use with tools like google authenticator, etc.
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:
|
open System
open System.Security.Cryptography
open System.Text
open System.Threading
let base32alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" |> Encoding.ASCII.GetBytes
let valToChar (b : byte) = base32alphabet.[int (b)]
let groupsOfAtMost (size : int) =
Seq.mapi (fun i x -> i / size, x)
>> Seq.groupBy (fun (i, _) -> i)
>> Seq.map (fun (_, vs) ->
vs
|> Seq.map (fun (_, b) -> b)
|> Seq.toList)
let base32encode (data : byte []) =
let leftover = data.Length % 5
let cvtdata =
data
|> groupsOfAtMost 5
|> Seq.map (fun x ->
match x with
| [ a; b; c; d; e ] -> (a, b, c, d, e)
| [ a; b; c; d ] -> (a, b, c, d, 0uy)
| [ a; b; c ] -> (a, b, c, 0uy, 0uy)
| [ a; b ] -> (a, b, 0uy, 0uy, 0uy)
| [ a ] -> (a, 0uy, 0uy, 0uy, 0uy)
| _ -> (0uy, 0uy, 0uy, 0uy, 0uy))
|> Seq.map (fun (c1, c2, c3, c4, c5) ->
[ valToChar (c1 >>> 3)
valToChar (((c1 &&& 0b111uy) <<< 2) ||| (c2 >>> 6))
valToChar (((c2 &&& 0b111110uy) >>> 1))
valToChar (((c2 &&& 0b1uy) <<< 4) ||| (c3 >>> 4))
valToChar (((c3 &&& 0b1111uy) <<< 1) ||| (c4 >>> 7))
valToChar (((c4 &&& 0b1111100uy) >>> 2))
valToChar (((c4 &&& 0b11uy) <<< 3) ||| (c5 >>> 5))
valToChar (((c5 &&& 0b11111uy))) ])
|> Seq.concat
|> Seq.toArray
let padding = "======" |> Encoding.ASCII.GetBytes
let cvtlen = cvtdata.Length
match leftover with
| 1 -> Array.blit padding 0 cvtdata (cvtlen - 7) 6
| 2 -> Array.blit padding 0 cvtdata (cvtlen - 5) 4
| 3 -> Array.blit padding 0 cvtdata (cvtlen - 4) 3
| 4 -> Array.blit padding 0 cvtdata (cvtlen - 2) 1
| _ -> ()
Encoding.ASCII.GetString cvtdata
let truncate (data : byte []) : uint32 =
let offset = int (Seq.last (data) &&& 0xfuy)
((uint32 (data.[offset + 0] &&& 0x7fuy) <<< 24) |||
(uint32 (data.[offset + 1] &&& 0xffuy) <<< 16) |||
(uint32 (data.[offset + 2] &&& 0xffuy) <<< 8 ) |||
(uint32 (data.[offset + 3] &&& 0xffuy))) % 1000000ul
let HMAC (K : byte []) (C : byte []) =
use hmac = new HMACSHA1(K)
hmac.ComputeHash C
let counter() =
uint64 (Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds)) / 30UL
|> BitConverter.GetBytes
|> Array.rev
let secret() = "ASDFASDFASDFASDFSADF" |> Encoding.ASCII.GetBytes
let TOTP() = (HMAC (secret()) (counter())) |> truncate
[<EntryPoint>]
let main _ =
let p =
base32encode (secret())
|> groupsOfAtMost 3
|> Seq.map (fun x -> String(Seq.toArray x) + " ")
|> Seq.reduce (+)
printfn "%s" p
for _ in 1..1000 do
printfn "%06d" (TOTP())
Thread.Sleep(10 * 1000)
0
|
namespace System
namespace System.Security
namespace System.Security.Cryptography
namespace System.Text
namespace System.Threading
val base32alphabet : byte []
Full name: Script.base32alphabet
type Encoding =
member BodyName : string
member Clone : unit -> obj
member CodePage : int
member DecoderFallback : DecoderFallback with get, set
member EncoderFallback : EncoderFallback with get, set
member EncodingName : string
member Equals : value:obj -> bool
member GetByteCount : chars:char[] -> int + 3 overloads
member GetBytes : chars:char[] -> byte[] + 5 overloads
member GetCharCount : bytes:byte[] -> int + 2 overloads
...
Full name: System.Text.Encoding
property Encoding.ASCII: Encoding
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
val valToChar : b:byte -> byte
Full name: Script.valToChar
val b : byte
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.byte
--------------------
type byte = Byte
Full name: Microsoft.FSharp.Core.byte
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
val groupsOfAtMost : size:int -> (seq<'a> -> seq<'a list>)
Full name: Script.groupsOfAtMost
val size : int
module Seq
from Microsoft.FSharp.Collections
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.mapi
val i : int
val x : 'a
val groupBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'Key * seq<'T>> (requires equality)
Full name: Microsoft.FSharp.Collections.Seq.groupBy
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val vs : seq<int * 'a>
val b : 'a
val toList : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.Seq.toList
val base32encode : data:byte [] -> string
Full name: Script.base32encode
val data : byte []
val leftover : int
property Array.Length: int
val cvtdata : byte []
val x : byte list
val a : byte
val c : byte
val d : byte
val e : byte
val c1 : byte
val c2 : byte
val c3 : byte
val c4 : byte
val c5 : byte
val concat : sources:seq<#seq<'T>> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.concat
val toArray : source:seq<'T> -> 'T []
Full name: Microsoft.FSharp.Collections.Seq.toArray
val padding : byte []
val cvtlen : int
type Array =
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...
Full name: System.Array
val blit : source:'T [] -> sourceIndex:int -> target:'T [] -> targetIndex:int -> count:int -> unit
Full name: Microsoft.FSharp.Collections.Array.blit
Encoding.GetString(bytes: byte []) : string
Encoding.GetString(bytes: byte [], index: int, count: int) : string
val truncate : data:byte [] -> uint32
Full name: Script.truncate
Multiple items
val uint32 : value:'T -> uint32 (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.uint32
--------------------
type uint32 = UInt32
Full name: Microsoft.FSharp.Core.uint32
val offset : int
val last : source:seq<'T> -> 'T
Full name: Microsoft.FSharp.Collections.Seq.last
Multiple items
val HMAC : K:byte [] -> C:byte [] -> byte []
Full name: Script.HMAC
--------------------
type HMAC =
inherit KeyedHashAlgorithm
member HashName : string with get, set
member Initialize : unit -> unit
member Key : byte[] with get, set
static member Create : unit -> HMAC + 1 overload
Full name: System.Security.Cryptography.HMAC
val K : byte []
val C : byte []
val hmac : HMACSHA1
Multiple items
type HMACSHA1 =
inherit HMAC
new : unit -> HMACSHA1 + 2 overloads
Full name: System.Security.Cryptography.HMACSHA1
--------------------
HMACSHA1() : unit
HMACSHA1(key: byte []) : unit
HMACSHA1(key: byte [], useManagedSha1: bool) : unit
HashAlgorithm.ComputeHash(buffer: byte []) : byte []
HashAlgorithm.ComputeHash(inputStream: IO.Stream) : byte []
HashAlgorithm.ComputeHash(buffer: byte [], offset: int, count: int) : byte []
val counter : unit -> byte []
Full name: Script.counter
Multiple items
val uint64 : value:'T -> uint64 (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.uint64
--------------------
type uint64 = UInt64
Full name: Microsoft.FSharp.Core.uint64
type Math =
static val PI : float
static val E : float
static member Abs : value:sbyte -> sbyte + 6 overloads
static member Acos : d:float -> float
static member Asin : d:float -> float
static member Atan : d:float -> float
static member Atan2 : y:float * x:float -> float
static member BigMul : a:int * b:int -> int64
static member Ceiling : d:decimal -> decimal + 1 overload
static member Cos : d:float -> float
...
Full name: System.Math
Math.Round(d: decimal) : decimal
Math.Round(a: float) : float
Math.Round(d: decimal, mode: MidpointRounding) : decimal
Math.Round(d: decimal, decimals: int) : decimal
Math.Round(value: float, mode: MidpointRounding) : float
Math.Round(value: float, digits: int) : float
Math.Round(d: decimal, decimals: int, mode: MidpointRounding) : decimal
Math.Round(value: float, digits: int, mode: MidpointRounding) : float
Multiple items
type DateTime =
struct
new : ticks:int64 -> DateTime + 10 overloads
member Add : value:TimeSpan -> DateTime
member AddDays : value:float -> DateTime
member AddHours : value:float -> DateTime
member AddMilliseconds : value:float -> DateTime
member AddMinutes : value:float -> DateTime
member AddMonths : months:int -> DateTime
member AddSeconds : value:float -> DateTime
member AddTicks : value:int64 -> DateTime
member AddYears : value:int -> DateTime
...
end
Full name: System.DateTime
--------------------
DateTime()
(+0 other overloads)
DateTime(ticks: int64) : unit
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
(+0 other overloads)
property DateTime.UtcNow: DateTime
type DateTimeKind =
| Unspecified = 0
| Utc = 1
| Local = 2
Full name: System.DateTimeKind
field DateTimeKind.Utc = 1
type BitConverter =
static val IsLittleEndian : bool
static member DoubleToInt64Bits : value:float -> int64
static member GetBytes : value:bool -> byte[] + 9 overloads
static member Int64BitsToDouble : value:int64 -> float
static member ToBoolean : value:byte[] * startIndex:int -> bool
static member ToChar : value:byte[] * startIndex:int -> char
static member ToDouble : value:byte[] * startIndex:int -> float
static member ToInt16 : value:byte[] * startIndex:int -> int16
static member ToInt32 : value:byte[] * startIndex:int -> int
static member ToInt64 : value:byte[] * startIndex:int -> int64
...
Full name: System.BitConverter
BitConverter.GetBytes(value: float) : byte []
BitConverter.GetBytes(value: float32) : byte []
BitConverter.GetBytes(value: uint64) : byte []
BitConverter.GetBytes(value: uint32) : byte []
BitConverter.GetBytes(value: uint16) : byte []
BitConverter.GetBytes(value: int64) : byte []
BitConverter.GetBytes(value: int) : byte []
BitConverter.GetBytes(value: int16) : byte []
BitConverter.GetBytes(value: char) : byte []
BitConverter.GetBytes(value: bool) : byte []
val rev : array:'T [] -> 'T []
Full name: Microsoft.FSharp.Collections.Array.rev
val secret : unit -> byte []
Full name: Script.secret
val TOTP : unit -> uint32
Full name: Script.TOTP
Multiple items
type EntryPointAttribute =
inherit Attribute
new : unit -> EntryPointAttribute
Full name: Microsoft.FSharp.Core.EntryPointAttribute
--------------------
new : unit -> EntryPointAttribute
val main : string [] -> int
Full name: Script.main
val p : String
val x : char list
Multiple items
type String =
new : value:char -> string + 7 overloads
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : value:obj -> int + 1 overload
member Contains : value:string -> bool
member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
member EndsWith : value:string -> bool + 2 overloads
member Equals : obj:obj -> bool + 2 overloads
member GetEnumerator : unit -> CharEnumerator
member GetHashCode : unit -> int
...
Full name: System.String
--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Encoding) : unit
val reduce : reduction:('T -> 'T -> 'T) -> source:seq<'T> -> 'T
Full name: Microsoft.FSharp.Collections.Seq.reduce
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Multiple items
type Thread =
inherit CriticalFinalizerObject
new : start:ThreadStart -> Thread + 3 overloads
member Abort : unit -> unit + 1 overload
member ApartmentState : ApartmentState with get, set
member CurrentCulture : CultureInfo with get, set
member CurrentUICulture : CultureInfo with get, set
member DisableComObjectEagerCleanup : unit -> unit
member ExecutionContext : ExecutionContext
member GetApartmentState : unit -> ApartmentState
member GetCompressedStack : unit -> CompressedStack
member GetHashCode : unit -> int
...
Full name: System.Threading.Thread
--------------------
Thread(start: ThreadStart) : unit
Thread(start: ParameterizedThreadStart) : unit
Thread(start: ThreadStart, maxStackSize: int) : unit
Thread(start: ParameterizedThreadStart, maxStackSize: int) : unit
Thread.Sleep(timeout: TimeSpan) : unit
Thread.Sleep(millisecondsTimeout: int) : unit
More information