Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
talla
enacl
Commits
ed3e31f2
Commit
ed3e31f2
authored
Jul 27, 2015
by
Jesper Louis Andersen
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5 from plumlife/master
Implementation of detached signatures
parents
89e28fea
35515e46
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
180 additions
and
36 deletions
+180
-36
c_src/enacl_nif.c
c_src/enacl_nif.c
+93
-21
eqc_test/enacl_eqc.erl
eqc_test/enacl_eqc.erl
+45
-9
src/enacl.erl
src/enacl.erl
+34
-5
src/enacl_nif.erl
src/enacl_nif.erl
+8
-1
No files found.
c_src/enacl_nif.c
View file @
ed3e31f2
...
...
@@ -322,7 +322,7 @@ ERL_NIF_TERM enif_crypto_box_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const a
static
ERL_NIF_TERM
enif_crypto_box_beforenm
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
k
,
pk
,
sk
;
if
(
(
argc
!=
2
)
||
(
!
enif_inspect_binary
(
env
,
argv
[
0
],
&
pk
))
||
...
...
@@ -331,20 +331,20 @@ ERL_NIF_TERM enif_crypto_box_beforenm(ErlNifEnv *env, int argc, ERL_NIF_TERM con
(
sk
.
size
!=
crypto_box_SECRETKEYBYTES
))
{
return
enif_make_badarg
(
env
);
}
if
(
!
enif_alloc_binary
(
crypto_box_BEFORENMBYTES
,
&
k
))
{
return
nacl_error_tuple
(
env
,
"alloc_failed"
);
}
crypto_box_beforenm
(
k
.
data
,
pk
.
data
,
sk
.
data
);
return
enif_make_binary
(
env
,
&
k
);
}
static
ERL_NIF_TERM
enif_crypto_box_afternm
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
result
,
m
,
nonce
,
k
;
if
(
(
argc
!=
3
)
||
(
!
enif_inspect_iolist_as_binary
(
env
,
argv
[
0
],
&
m
))
||
...
...
@@ -355,13 +355,13 @@ ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM cons
(
k
.
size
!=
crypto_box_BEFORENMBYTES
))
{
return
enif_make_badarg
(
env
);
}
if
(
!
enif_alloc_binary
(
m
.
size
,
&
result
))
{
return
nacl_error_tuple
(
env
,
"alloc_failed"
);
}
crypto_box_afternm
(
result
.
data
,
m
.
data
,
m
.
size
,
nonce
.
data
,
k
.
data
);
return
enif_make_sub_binary
(
env
,
enif_make_binary
(
env
,
&
result
),
...
...
@@ -372,7 +372,7 @@ ERL_NIF_TERM enif_crypto_box_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM cons
static
ERL_NIF_TERM
enif_crypto_box_open_afternm
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
result
,
m
,
nonce
,
k
;
if
(
(
argc
!=
3
)
||
(
!
enif_inspect_iolist_as_binary
(
env
,
argv
[
0
],
&
m
))
||
...
...
@@ -383,16 +383,16 @@ ERL_NIF_TERM enif_crypto_box_open_afternm(ErlNifEnv *env, int argc, ERL_NIF_TERM
(
k
.
size
!=
crypto_box_BEFORENMBYTES
))
{
return
enif_make_badarg
(
env
);
}
if
(
!
enif_alloc_binary
(
m
.
size
,
&
result
))
{
return
nacl_error_tuple
(
env
,
"alloc_failed"
);
}
if
(
0
!=
crypto_box_open_afternm
(
result
.
data
,
m
.
data
,
m
.
size
,
nonce
.
data
,
k
.
data
))
{
enif_release_binary
(
&
result
);
return
nacl_error_tuple
(
env
,
"failed_verification"
);
}
return
enif_make_sub_binary
(
env
,
enif_make_binary
(
env
,
&
result
),
...
...
@@ -432,6 +432,11 @@ ERL_NIF_TERM enif_crypto_sign_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM con
return
enif_make_tuple2
(
env
,
enif_make_binary
(
env
,
&
pk
),
enif_make_binary
(
env
,
&
sk
));
}
/*
int crypto_sign(unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *sk);
*/
static
ERL_NIF_TERM
enif_crypto_sign
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
m
,
sk
,
sm
;
...
...
@@ -457,6 +462,11 @@ ERL_NIF_TERM enif_crypto_sign(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[
return
enif_make_sub_binary
(
env
,
enif_make_binary
(
env
,
&
sm
),
0
,
smlen
);
}
/*
int crypto_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk);
*/
static
ERL_NIF_TERM
enif_crypto_sign_open
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
m
,
sm
,
pk
;
...
...
@@ -485,6 +495,65 @@ ERL_NIF_TERM enif_crypto_sign_open(ErlNifEnv *env, int argc, ERL_NIF_TERM const
}
}
/*
int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *sk);
*/
static
ERL_NIF_TERM
enif_crypto_sign_detached
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
m
,
sk
,
sig
;
unsigned
long
long
siglen
;
if
(
(
argc
!=
2
)
||
(
!
enif_inspect_iolist_as_binary
(
env
,
argv
[
0
],
&
m
))
||
(
!
enif_inspect_binary
(
env
,
argv
[
1
],
&
sk
)))
{
return
enif_make_badarg
(
env
);
}
if
(
sk
.
size
!=
crypto_sign_SECRETKEYBYTES
)
{
return
enif_make_badarg
(
env
);
}
if
(
!
enif_alloc_binary
(
crypto_sign_BYTES
,
&
sig
))
{
return
nacl_error_tuple
(
env
,
"alloc_failed"
);
}
crypto_sign_detached
(
sig
.
data
,
&
siglen
,
m
.
data
,
m
.
size
,
sk
.
data
);
return
enif_make_binary
(
env
,
&
sig
);
}
/*
int crypto_sign_verify_detached(const unsigned char *sig,
const unsigned char *m,
unsigned long long mlen,
const unsigned char *pk);
*/
static
ERL_NIF_TERM
enif_crypto_sign_verify_detached
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
m
,
sig
,
pk
;
if
(
(
argc
!=
3
)
||
(
!
enif_inspect_binary
(
env
,
argv
[
0
],
&
sig
))
||
(
!
enif_inspect_iolist_as_binary
(
env
,
argv
[
1
],
&
m
))
||
(
!
enif_inspect_binary
(
env
,
argv
[
2
],
&
pk
)))
{
return
enif_make_badarg
(
env
);
}
if
(
pk
.
size
!=
crypto_sign_PUBLICKEYBYTES
)
{
return
enif_make_badarg
(
env
);
}
if
(
0
==
crypto_sign_verify_detached
(
sig
.
data
,
m
.
data
,
m
.
size
,
pk
.
data
))
{
return
enif_make_atom
(
env
,
"true"
);
}
else
{
return
enif_make_atom
(
env
,
"false"
);
}
}
/* Secret key cryptography */
static
...
...
@@ -770,17 +839,17 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[
{
size_t
req_size
;
ErlNifBinary
result
;
if
((
argc
!=
1
)
||
(
!
enif_get_uint64
(
env
,
argv
[
0
],
&
req_size
)))
{
return
enif_make_badarg
(
env
);
}
if
(
!
enif_alloc_binary
(
req_size
,
&
result
))
{
return
nacl_error_tuple
(
env
,
"alloc_failed"
);
}
randombytes
(
result
.
data
,
result
.
size
);
return
enif_make_binary
(
env
,
&
result
);
}
...
...
@@ -841,7 +910,7 @@ static
ERL_NIF_TERM
enif_scramble_block_16
(
ErlNifEnv
*
env
,
int
argc
,
ERL_NIF_TERM
const
argv
[])
{
ErlNifBinary
in
,
out
,
key
;
if
(
(
argc
!=
2
)
||
(
!
enif_inspect_binary
(
env
,
argv
[
0
],
&
in
))
||
...
...
@@ -849,13 +918,13 @@ ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const
(
in
.
size
!=
16
)
||
(
key
.
size
!=
32
))
{
return
enif_make_badarg
(
env
);
}
if
(
!
enif_alloc_binary
(
in
.
size
,
&
out
))
{
return
nacl_error_tuple
(
env
,
"alloc_failed"
);
}
crypto_block
(
out
.
data
,
in
.
data
,
key
.
data
);
return
enif_make_binary
(
env
,
&
out
);
}
...
...
@@ -886,6 +955,9 @@ static ErlNifFunc nif_funcs[] = {
{
"crypto_sign_open_b"
,
2
,
enif_crypto_sign_open
},
{
"crypto_sign_open"
,
2
,
enif_crypto_sign_open
,
ERL_NIF_DIRTY_JOB_CPU_BOUND
},
{
"crypto_sign_detached"
,
2
,
enif_crypto_sign_detached
,
ERL_NIF_DIRTY_JOB_CPU_BOUND
},
{
"crypto_sign_verify_detached"
,
3
,
enif_crypto_sign_verify_detached
,
ERL_NIF_DIRTY_JOB_CPU_BOUND
},
{
"crypto_secretbox_NONCEBYTES"
,
0
,
enif_crypto_secretbox_NONCEBYTES
},
{
"crypto_secretbox_ZEROBYTES"
,
0
,
enif_crypto_secretbox_ZEROBYTES
},
{
"crypto_secretbox_BOXZEROBYTES"
,
0
,
enif_crypto_secretbox_BOXZEROBYTES
},
...
...
@@ -931,7 +1003,7 @@ static ErlNifFunc nif_funcs[] = {
{
"randombytes_b"
,
1
,
enif_randombytes
},
{
"randombytes"
,
1
,
enif_randombytes
,
ERL_NIF_DIRTY_JOB_CPU_BOUND
},
{
"scramble_block_16"
,
2
,
enif_scramble_block_16
}
};
...
...
eqc_test/enacl_eqc.erl
View file @
ed3e31f2
...
...
@@ -2,6 +2,13 @@
-
include_lib
(
"eqc/include/eqc.hrl"
).
-
compile
(
export_all
).
%% dummy test property
prop_append
()
->
?
FORALL
({
Xs
,
Ys
},{
list
(
int
()),
list
(
int
())},
lists
:
reverse
(
Xs
++
Ys
)
==
lists
:
reverse
(
Ys
)
++
lists
:
reverse
(
Xs
)).
non_byte_int
()
->
oneof
([
?
LET
(
N
,
nat
(),
-
(
N
+
1
)),
...
...
@@ -10,7 +17,7 @@ non_byte_int() ->
g_iolist
()
->
?
SIZED
(
Sz
,
g_iolist
(
Sz
)).
g_iolist
(
0
)
->
fault
(
oneof
([
...
...
@@ -30,7 +37,7 @@ g_iolist(N) ->
{
1
,
g_iolist
(
0
)},
{
N
,
?
LAZY
(
list
(
oneof
([
char
(),
binary
(),
g_iolist
(
N
div
4
)])))}
])).
g_iodata
()
->
fault
(
oneof
([
elements
([
a
,
b
,
c
]),
real
()]),
...
...
@@ -60,12 +67,12 @@ g_binary_bad(Sz) ->
{
1
,
int
()},
{
1
,
g_iodata
()}
]).
v_binary
(
Sz
,
N
)
when
is_binary
(
N
)
->
byte_size
(
N
)
==
Sz
;
v_binary
(_,
_)
->
false
.
%% Typical generators based on the binaries
nonce
()
->
g_binary
(
enacl
:
box_nonce_size
()).
nonce_valid
(
N
)
->
v_binary
(
enacl
:
box_nonce_size
(),
N
).
...
...
@@ -73,7 +80,7 @@ nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N).
%% Generator of natural numbers
g_nat
()
->
fault
(
g_nat_bad
(),
nat
()).
g_nat_bad
()
->
oneof
([
elements
([
a
,
b
,
c
]),
...
...
@@ -242,7 +249,7 @@ prop_afternm_correct() ->
end
end
end
).
%% SIGNATURES
%% ----------
...
...
@@ -279,12 +286,12 @@ sign_keypair_public_valid(#{ public := Public })
when
is_binary
(
Public
)
->
byte_size
(
Public
)
==
enacl
:
sign_keypair_public_size
();
sign_keypair_public_valid
(_)
->
false
.
sign_keypair_secret_valid
(
#
{
secret
:
=
Secret
})
when
is_binary
(
Secret
)
->
byte_size
(
Secret
)
==
enacl
:
sign_keypair_secret_size
();
sign_keypair_secret_valid
(_)
->
false
.
sign_keypair_valid
(
KP
)
->
sign_keypair_public_valid
(
KP
)
andalso
sign_keypair_secret_valid
(
KP
).
...
...
@@ -340,7 +347,7 @@ prop_sign_open() ->
false
->
badargs
(
fun
()
->
enacl
:
sign_open
(
SignMsg
,
PK
)
end
)
end
)).
%% CRYPTO SECRET BOX
%% -------------------------------
...
...
@@ -667,3 +674,32 @@ badargs(Thunk) ->
catch
error
:
badarg
->
true
end
.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Joel Test Blobs
test_basic_signing
()
->
#
{
public
:
=
PK0
,
secret
:
=
SK0
}
=
enacl
:
sign_keypair
(),
#
{
public
:
=
PK1
,
secret
:
=
SK1
}
=
enacl
:
sign_keypair
(),
MSG0
=
<<
"This is super s3Kr3t, srsly!"
>>
,
[
%% (+) Sign and open using valid keypair
case
enacl
:
sign_open
(
enacl
:
sign
(
MSG0
,
SK0
),
PK0
)
of
{
ok
,
MSG1
}
->
MSG0
==
MSG1
;
_
->
false
end
,
%% (-) Sign and open using invalid keypair
case
enacl
:
sign_open
(
enacl
:
sign
(
MSG0
,
SK0
),
PK1
)
of
{
error
,
failed_verification
}
->
true
;
_
->
false
end
,
%% (+) Detached mode sig and verify
{
enacl
:
sign_verify_detached
(
enacl
:
sign_detached
(
MSG0
,
SK0
),
MSG0
,
PK0
)
,
enacl
:
sign_verify_detached
(
enacl
:
sign_detached
(
MSG0
,
SK1
),
MSG0
,
PK1
)
}
,
%% (-) Incorrect sigs/PKs/messages given during verify
{
false
==
enacl
:
sign_verify_detached
(
enacl
:
sign_detached
(
MSG0
,
SK0
),
MSG0
,
PK1
)
,
false
==
enacl
:
sign_verify_detached
(
enacl
:
sign_detached
(
MSG0
,
SK1
),
MSG0
,
PK0
)
,
false
==
enacl
:
sign_verify_detached
(
enacl
:
sign_detached
(
MSG0
,
SK0
),
<<
"bzzt"
>>
,
PK0
)
}
].
src/enacl.erl
View file @
ed3e31f2
...
...
@@ -29,12 +29,14 @@
box_public_key_bytes
/
0
,
box_secret_key_bytes
/
0
,
box_beforenm_bytes
/
0
,
sign_keypair_public_size
/
0
,
sign_keypair_secret_size
/
0
,
sign_keypair
/
0
,
sign
/
2
,
sign_open
/
2
sign_open
/
2
,
sign_detached
/
2
,
sign_verify_detached
/
3
]).
%% Secret key crypto
...
...
@@ -251,7 +253,7 @@ box_beforenm(PK, SK) ->
R
=
enacl_nif
:
crypto_box_beforenm
(
PK
,
SK
),
erlang
:
bump_reductions
(
?
BOX_BEFORENM_REDUCTIONS
),
R
.
%% @doc box_afternm/3 works like `box/4' but uses a precomputed key
%%
%% Calling `box_afternm(M, Nonce, K)' for a precomputed key `K = box_beforenm(PK, SK)' works exactly as
...
...
@@ -323,7 +325,7 @@ box_beforenm_bytes() ->
%% @private
sign_keypair_public_size
()
->
enacl_nif
:
crypto_sign_PUBLICKEYBYTES
().
%% @private
sign_keypair_secret_size
()
->
enacl_nif
:
crypto_sign_SECRETKEYBYTES
().
...
...
@@ -380,6 +382,33 @@ sign_open(SM, PK) ->
end
end
.
%% @doc sign_detached/2 computes a digital signature given a message and a secret key.
%%
%% Given a message `M' and a secret key `SK' the function will compute the digital signature `DS'.
%% @end
-
spec
sign_detached
(
M
,
SK
)
->
DS
when
M
::
iodata
(),
SK
::
binary
(),
DS
::
binary
().
sign_detached
(
M
,
SK
)
->
enacl_nif
:
crypto_sign_detached
(
M
,
SK
).
%% @doc sign_verify_detached/3 verifies the given signature against the given
%% message for the given public key.
%%
%% Given a signature `SIG', a message `M', and a public key `PK', the function computes
%% true iff the `SIG' is valid for `M' and `PK'.
-
spec
sign_verify_detached
(
SIG
,
M
,
PK
)
->
{
ok
,
M
}
|
{
error
,
failed_verification
}
when
SIG
::
binary
(),
M
::
iodata
(),
PK
::
binary
().
sign_verify_detached
(
SIG
,
M
,
PK
)
->
case
enacl_nif
:
crypto_sign_verify_detached
(
SIG
,
M
,
PK
)
of
true
->
{
ok
,
M
};
false
->
{
error
,
failed_verification
}
end
.
%% @private
-
spec
box_secret_key_bytes
()
->
pos_integer
().
box_secret_key_bytes
()
->
...
...
@@ -433,7 +462,7 @@ secretbox_open(CipherText, Nonce, Key) ->
Bin
when
is_binary
(
Bin
)
->
{
ok
,
Bin
}
end
end
.
%% @doc secretbox_nonce_size/0 returns the size of the secretbox nonce
%%
%% When encrypting with a secretbox, the nonce must have this size
...
...
src/enacl_nif.erl
View file @
ed3e31f2
...
...
@@ -31,7 +31,11 @@
crypto_sign_b
/
2
,
crypto_sign_keypair
/
0
,
crypto_sign_open
/
2
,
crypto_sign_open_b
/
2
crypto_sign_open_b
/
2
,
crypto_sign_detached
/
2
,
crypto_sign_verify_detached
/
3
]).
%% Secret key crypto
...
...
@@ -144,6 +148,9 @@ crypto_sign_b(_M, _SK) -> erlang:nif_error(nif_not_loaded).
crypto_sign_open
(_
SignedMessage
,
_
PK
)
->
erlang
:
nif_error
(
nif_not_loaded
).
crypto_sign_open_b
(_
SignedMessage
,
_
PK
)
->
erlang
:
nif_error
(
nif_not_loaded
).
crypto_sign_detached
(_
M
,
_
SK
)
->
erlang
:
nif_error
(
nif_not_loaded
).
crypto_sign_verify_detached
(_
SIG
,
_
M
,
_
PK
)
->
erlang
:
nif_error
(
nif_not_loaded
).
crypto_secretbox_NONCEBYTES
()
->
erlang
:
nif_error
(
nif_not_loaded
).
crypto_secretbox_ZEROBYTES
()
->
erlang
:
nif_error
(
nif_not_loaded
).
crypto_secretbox_KEYBYTES
()
->
erlang
:
nif_error
(
nif_not_loaded
).
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment