Skip to content

Commit

Permalink
Isolate crypto
Browse files Browse the repository at this point in the history
Also add in a salt generator
  • Loading branch information
xurtis committed Jul 12, 2017
1 parent 5d4650b commit 4e46c33
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 63 deletions.
109 changes: 109 additions & 0 deletions source/Crypto.elm
Original file line number Diff line number Diff line change
@@ -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
64 changes: 10 additions & 54 deletions source/Data.elm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- Data structures
module Data exposing (..)

import Sha exposing (..)
import Crypto exposing (..)
import Dict exposing (Dict, get)
import Keyboard
import Char
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -112,7 +69,7 @@ init flags =
flags.hash
flags.salt
""
, Random.generate GenMask (genMask (Array.fromList alphas) 0)
, newMask GenMask
)

-- Initial Map
Expand Down Expand Up @@ -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
Expand All @@ -178,6 +134,6 @@ subscriptions msg =
in
Sub.batch
[ Keyboard.presses pressMessage
, Sha.sha_result Hash
, Crypto.sha_result Hash
]

2 changes: 0 additions & 2 deletions source/Main.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
-- NSA Crypto App

import Sha exposing (..)
import Data exposing (init, update, subscriptions)
import Display exposing (view)
import Html exposing (programWithFlags)
Expand Down
7 changes: 0 additions & 7 deletions source/Sha.elm

This file was deleted.

0 comments on commit 4e46c33

Please sign in to comment.