3 people like it.

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

Link:http://fssnip.net/pE
Posted:9 years ago
Author:@sillyotter
Tags: totp , authentication