Skip to content

Commit

Permalink
Added simple encrypt/decrypt for lazy(ish) / non security oriented de…
Browse files Browse the repository at this point in the history
…velopers
  • Loading branch information
aforward committed Dec 14, 2014
1 parent cf8427c commit 65f5316
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 2 deletions.
72 changes: 72 additions & 0 deletions lib/safetybox.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
defmodule Safetybox do

alias Cryptex.KeyGenerator, as: K
alias Cryptex.MessageEncryptor, as: E
alias Cryptex.MessageVerifier, as: V

@global_salt "4Yw7kLLAjFfxtqHzttpRhmPrEqqXqqrMHdgmcgUNDq"
@global_secret "FzxZRcf3xHxerDWXECwpWJVu2dwfyagTyPHmXcVpkv"

@moduledoc """
# Safetybox a collection of security oriented functions
# This is oriented towards individuals that store passwords
# directly in their code, or some other not-so-hard-to-find location
## Dependency
{ :safetybox, "~> 0.1" }
## Usage
Expand Down Expand Up @@ -32,10 +41,73 @@ defmodule Safetybox do
|> :erlang.list_to_bitstring
end

@doc """
If you don't yet need a secret or a salt (e.g. very early prototype), but you want some thigns encrypted
then use the :default secret. Better than nothing, but not much.
Safetybox.encrypt("helloworld", :default)
"""
def encrypt(plaintext, :default), do: encrypt(plaintext, @global_secret, @global_salt)

@doc """
One tiny secret for a developer, one giant leap in security. Pick a secret within your application
(or ENV variable), to better prevent your strings being decrypted
Safetybox.encrypt("helloworld","mysecretkey")
"""
def encrypt(plaintext, secret), do: encrypt(plaintext, secret, @global_salt)

@doc """
Convert a plaintext string into a decryptable string by providing a secret
Safetybox.encrypt("helloworld","mysecretkey", "mysecretsalt")
"""
def encrypt(plaintext, secret, salt) do
secret
|> crypt(salt)
|> E.encrypt_and_sign(plaintext)
end

@doc """
Decrypt some obscure text that was generated by encrypt
enc = Safetybox.encrypt("helloworld")
Safetybox.decrypt(env)
"""
def decrypt(obscuretext), do: decrypt(obscuretext, @global_secret, @global_salt)

@doc """
Decrypt some obscure text that was generated by encrypt
enc = Safetybox.encrypt("helloworld")
Safetybox.decrypt(env)
"""
def decrypt(obscuretext, secret), do: decrypt(obscuretext, secret, @global_salt)

@doc """
Take an encrypted string, and convert it back to plaintext, must use the same secret and salt
enc = Safetybox.encrypt("helloworld","mysecretkey", "mysecretsalt")
Safetybox.encrypt("helloworld","mysecretkey", "mysecretsalt")
"""
def decrypt(obscuretext, secret, salt) do
secret
|> crypt(salt)
|> decrypt_and_verify(obscuretext)
end

@doc """
Compare a plaintext string to it's encrypted version to test if they match.
Safetybox.is_decrypted("helloworld", "dasdf!@#CASD")
"""
def is_decrypted(plaintext, encrypted), do: encrypt(plaintext) == encrypted


defp crypt(secret, salt) do
secret
|> K.generate(salt)
|> E.new(K.generate(secret, "signed #{salt}"))
end

defp decrypt_and_verify(cryptor, obscuretext) do
case V.verify(cryptor.sign_secret, obscuretext, :null) do
:error -> :error
{:ok, _unsigned} -> E.decrypt_and_verify(cryptor, obscuretext)
end
end

end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Safetybox.Mixfile do
def project do
[
app: :safetybox,
version: "0.0.2",
version: "0.1.0",
elixir: "~> 1.0",
deps: deps,

Expand Down Expand Up @@ -41,6 +41,7 @@ defmodule Safetybox.Mixfile do
[
{:ex_doc, "~> 0.6", only: :dev},
{:earmark, "~> 0.1"},
{:cryptex, "~> 0.0.1"},
]
end
end
3 changes: 2 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
%{"earmark": {:hex, :earmark, "0.1.12"},
%{"cryptex": {:hex, :cryptex, "0.0.1"},
"earmark": {:hex, :earmark, "0.1.12"},
"ex_doc": {:hex, :ex_doc, "0.6.2"}}
26 changes: 26 additions & 0 deletions test/safetybox_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,30 @@ defmodule SafetyboxTest do
assert S.is_decrypted("", S.encrypt("")) == true
end

test "encrypt / decrypt (default)" do
assert S.decrypt(S.encrypt("helloworld", :default)) == "helloworld"
assert S.decrypt(S.encrypt("goodbyeworld", :default)) == "goodbyeworld"
end

test "encrypt / decrypt (secret)" do
assert S.decrypt(S.encrypt("helloworld", "mysecret"), "yoursecret") == :error
assert S.decrypt(S.encrypt("goodbyeworld", "mysecret"), "yoursecret") != "goodbyeworld"

assert S.decrypt(S.encrypt("helloworld", "mysecret"), "mysecret") == "helloworld"
assert S.decrypt(S.encrypt("goodbyeworld", "mysecret"), "mysecret") == "goodbyeworld"
end

test "encrypt / decrypt (secret, salt)" do
assert S.decrypt(S.encrypt("helloworld", "mysecret", "mysalt"), "yoursecret", "mysalt") == :error
assert S.decrypt(S.encrypt("goodbyeworld", "mysecret", "mysalt"), "yoursecret", "mysalt") != "goodbyeworld"
assert S.decrypt(S.encrypt("helloworld", "mysecret", "mysalt"), "mysalt", "yoursalt") != "helloworld"
assert S.decrypt(S.encrypt("goodbyeworld", "mysecret", "mysalt"), "mysalt", "yoursalt") != "goodbyeworld"
assert S.decrypt(S.encrypt("helloworld", "mysecret", "mysalt"), "yoursecret", "yoursalt") != "helloworld"
assert S.decrypt(S.encrypt("goodbyeworld", "mysecret", "mysalt"), "yoursecret", "yoursalt") != "goodbyeworld"

assert S.decrypt(S.encrypt("helloworld", "mysecret", "mysalt"), "mysecret", "mysalt") == "helloworld"
assert S.decrypt(S.encrypt("goodbyeworld", "mysecret", "mysalt"), "mysecret", "mysalt") == "goodbyeworld"
end


end

0 comments on commit 65f5316

Please sign in to comment.