From 4e46c3329d3e24c8b996bac796b8225236fa712c Mon Sep 17 00:00:00 2001 From: Curtis Millar Date: Wed, 12 Jul 2017 20:35:44 +1000 Subject: [PATCH] Isolate crypto Also add in a salt generator --- source/Crypto.elm | 109 ++++++++++++++++++++++++++++++++++++++++++++++ source/Data.elm | 64 +++++---------------------- source/Main.elm | 2 - source/Sha.elm | 7 --- 4 files changed, 119 insertions(+), 63 deletions(-) create mode 100644 source/Crypto.elm delete mode 100644 source/Sha.elm diff --git a/source/Crypto.elm b/source/Crypto.elm new file mode 100644 index 0000000..203a9be --- /dev/null +++ b/source/Crypto.elm @@ -0,0 +1,109 @@ +port module Crypto exposing (..) + +import Random exposing (Generator) +import Array exposing (Array) +import List exposing (map) +import Dict +import String +import Bitwise exposing (and, shiftRightBy) + +-- Hashing + +-- Port for sending out data to be hashed +port sha256 : String -> Cmd msg + +-- Port for listening to hashed messages +port sha_result : (String -> msg) -> Sub msg + +-- Monoalphabetic Substitution +type alias MaskStep = (Array Char, Int) + +-- Alphabetical characters +alphas = String.toList (String.toUpper "abcdefghijklmnopqrstuvwxyz") +numAlphas = List.length alphas + +-- Letter shuffling +swapLetters : Array Char -> Int -> Int -> Array Char +swapLetters chars a b = + let + letterA = Array.get a chars |> Maybe.withDefault '?' + letterB = Array.get b chars |> Maybe.withDefault '?' + in + chars |> Array.set a letterB |> Array.set b letterA + +-- String shuffling generator +genMask : MaskStep -> Generator MaskStep +genMask step = + let + (mask, next) = step + alphaInt = Random.int 0 (numAlphas - 1) + fromInt i = + ( swapLetters mask next i + , next + 1 + ) + in + Random.map fromInt alphaInt + +-- Continue to next step of mask generation +stepMask : (MaskStep -> msg) -> MaskStep -> Cmd msg +stepMask message step = + let + (_, count) = step + in + if (count >= numAlphas) then + Cmd.none + else + Random.generate message (genMask step) + +-- Start generating a mash +newMask : (MaskStep -> msg) -> Cmd msg +newMask message = + stepMask message (Array.fromList alphas, 0) + +-- Apply a substitution mask on the message +substitute : MaskStep -> String -> String +substitute step text = + let + (mask, _) = step + zip a b = + case (List.head a) of + Nothing -> [] + Just a_head -> + case (List.head b) of + Nothing -> [] + Just b_head -> + (a_head, b_head) :: zip + (Maybe.withDefault [] (List.tail a)) + (Maybe.withDefault [] (List.tail b)) + maskDict = mask |> Array.toList |> zip alphas |> Dict.fromList + subChar c = Dict.get c maskDict |> Maybe.withDefault c + in + map subChar (String.toList text) |> String.fromList + +-- Encode an int as hex +hexchars : Array Char +hexchars = + "0123456789abcdef" + |> String.toList + |> Array.fromList + +hexEncode : Int -> String +hexEncode value = + let + tail = and value 15 + char = Array.get tail hexchars |> Maybe.withDefault '0' + init = shiftRightBy 4 value + in + if (value /= 0) then + char |> String.fromChar |> (++) (hexEncode init) + else + "" + +-- Generate a salt +genSalt : (String -> msg) -> Cmd msg +genSalt message = + let + saltGenerator = + Random.map hexEncode (Random.int Random.minInt Random.maxInt) + in + Random.generate message saltGenerator diff --git a/source/Data.elm b/source/Data.elm index 9dd9218..51c59ee 100644 --- a/source/Data.elm +++ b/source/Data.elm @@ -1,7 +1,7 @@ -- Data structures module Data exposing (..) -import Sha exposing (..) +import Crypto exposing (..) import Dict exposing (Dict, get) import Keyboard import Char @@ -37,54 +37,11 @@ type alias Model = , hash : String } --- Alphabetical characters -alphas = String.toList (String.toUpper "abcdefghijklmnopqrstuvwxyz") -numAlphas = List.length alphas - -swapLetters : Array Char -> Int -> Int -> Array Char -swapLetters chars a b = - let - letterA = Array.get a chars |> Maybe.withDefault '?' - letterB = Array.get b chars |> Maybe.withDefault '?' - in - chars |> Array.set a letterB |> Array.set b letterA - --- String shuffling generator -genMask : Array Char -> Int -> Generator (Array Char, Int) -genMask mask next = - let - alphaInt = Random.int 0 (numAlphas - 1) - fromInt i = - ( swapLetters mask next i - , next + 1 - ) - in - Random.map fromInt alphaInt - --- Apply a substitution on the message -substitute : List Char -> String -> String -substitute mask text = - let - zip a b = - case (List.head a) of - Nothing -> [] - Just a_head -> - case (List.head b) of - Nothing -> [] - Just b_head -> - (a_head, b_head) :: zip - (Maybe.withDefault [] (List.tail a)) - (Maybe.withDefault [] (List.tail b)) - maskDict = zip alphas mask |> Dict.fromList - subChar c = Dict.get c maskDict |> Maybe.withDefault c - in - map subChar (String.toList text) |> String.fromList - -messageSubstitute : Array Char -> List String -> List String -messageSubstitute mask message = +messageSubstitute : MaskStep -> List String -> List String +messageSubstitute step message = message |> String.join " " - |> substitute (Array.toList mask) + |> substitute step |> String.words @@ -112,7 +69,7 @@ init flags = flags.hash flags.salt "" - , Random.generate GenMask (genMask (Array.fromList alphas) 0) + , newMask GenMask ) -- Initial Map @@ -152,11 +109,10 @@ update msg model = ( { model | hash = h } , Cmd.none ) - GenMask (mask, next) -> - if (next >= numAlphas) then - ({ model | message = messageSubstitute mask model.message}, Cmd.none) - else - (model, Random.generate GenMask (genMask mask next)) + GenMask step -> + ( { model | message = messageSubstitute step model.message} + , stepMask GenMask step + ) -- Get a hash of the current decode decodeCheck : Model -> Cmd Msg @@ -178,6 +134,6 @@ subscriptions msg = in Sub.batch [ Keyboard.presses pressMessage - , Sha.sha_result Hash + , Crypto.sha_result Hash ] diff --git a/source/Main.elm b/source/Main.elm index f12466c..3532517 100644 --- a/source/Main.elm +++ b/source/Main.elm @@ -1,6 +1,4 @@ -- NSA Crypto App - -import Sha exposing (..) import Data exposing (init, update, subscriptions) import Display exposing (view) import Html exposing (programWithFlags) diff --git a/source/Sha.elm b/source/Sha.elm deleted file mode 100644 index 2f2266c..0000000 --- a/source/Sha.elm +++ /dev/null @@ -1,7 +0,0 @@ -port module Sha exposing (..) - --- Port for sending out data to be hashed -port sha256 : String -> Cmd msg - --- Port for listening to hashed messages -port sha_result : (String -> msg) -> Sub msg