Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
opendht
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
savoirfairelinux
opendht
Commits
cdcaebbc
Commit
cdcaebbc
authored
9 years ago
by
Adrien Béraud
Browse files
Options
Downloads
Patches
Plain Diff
crypto: use AES-GCM + RSA for encryption rather than RSA-ECB
parent
70dfb4bb
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
include/opendht/crypto.h
+12
-0
12 additions, 0 deletions
include/opendht/crypto.h
src/crypto.cpp
+138
-32
138 additions, 32 deletions
src/crypto.cpp
with
150 additions
and
32 deletions
include/opendht/crypto.h
+
12
−
0
View file @
cdcaebbc
...
@@ -110,6 +110,7 @@ struct PublicKey
...
@@ -110,6 +110,7 @@ struct PublicKey
private
:
private
:
PublicKey
(
const
PublicKey
&
)
=
delete
;
PublicKey
(
const
PublicKey
&
)
=
delete
;
PublicKey
&
operator
=
(
const
PublicKey
&
)
=
delete
;
PublicKey
&
operator
=
(
const
PublicKey
&
)
=
delete
;
void
encryptBloc
(
const
uint8_t
*
src
,
size_t
src_size
,
uint8_t
*
dst
,
size_t
dst_size
)
const
;
};
};
/**
/**
...
@@ -145,6 +146,7 @@ struct PrivateKey
...
@@ -145,6 +146,7 @@ struct PrivateKey
/**
/**
* Generate a new RSA key pair
* Generate a new RSA key pair
* @param key_length : size of the modulus in bits
* @param key_length : size of the modulus in bits
* Minimim value: 2048
* Recommended values: 4096, 8192
* Recommended values: 4096, 8192
*/
*/
static
PrivateKey
generate
(
unsigned
key_length
=
4096
);
static
PrivateKey
generate
(
unsigned
key_length
=
4096
);
...
@@ -154,6 +156,7 @@ struct PrivateKey
...
@@ -154,6 +156,7 @@ struct PrivateKey
private
:
private
:
PrivateKey
(
const
PrivateKey
&
)
=
delete
;
PrivateKey
(
const
PrivateKey
&
)
=
delete
;
PrivateKey
&
operator
=
(
const
PrivateKey
&
)
=
delete
;
PrivateKey
&
operator
=
(
const
PrivateKey
&
)
=
delete
;
Blob
decryptBloc
(
const
uint8_t
*
src
,
size_t
src_size
)
const
;
friend
dht
::
crypto
::
Identity
dht
::
crypto
::
generateIdentity
(
const
std
::
string
&
,
dht
::
crypto
::
Identity
,
unsigned
key_length
);
friend
dht
::
crypto
::
Identity
dht
::
crypto
::
generateIdentity
(
const
std
::
string
&
,
dht
::
crypto
::
Identity
,
unsigned
key_length
);
};
};
...
@@ -301,6 +304,15 @@ private:
...
@@ -301,6 +304,15 @@ private:
friend
dht
::
crypto
::
Identity
dht
::
crypto
::
generateIdentity
(
const
std
::
string
&
,
dht
::
crypto
::
Identity
,
unsigned
key_length
);
friend
dht
::
crypto
::
Identity
dht
::
crypto
::
generateIdentity
(
const
std
::
string
&
,
dht
::
crypto
::
Identity
,
unsigned
key_length
);
};
};
/**
* AES-GCM encryption. Key must be 128, 192 or 126 bits long (16, 24 or 32 bytes).
*/
Blob
aesEncrypt
(
const
Blob
&
data
,
const
Blob
&
key
);
/**
* AES-GCM decryption.
*/
Blob
aesDecrypt
(
const
Blob
&
data
,
const
Blob
&
key
);
}
}
}
}
This diff is collapsed.
Click to expand it.
src/crypto.cpp
+
138
−
32
View file @
cdcaebbc
...
@@ -35,14 +35,17 @@ extern "C" {
...
@@ -35,14 +35,17 @@ extern "C" {
#include
<gnutls/gnutls.h>
#include
<gnutls/gnutls.h>
#include
<gnutls/abstract.h>
#include
<gnutls/abstract.h>
#include
<gnutls/x509.h>
#include
<gnutls/x509.h>
#include
<nettle/gcm.h>
#include
<nettle/aes.h>
}
}
#include
<random>
#include
<random>
#include
<sstream>
#include
<sstream>
#include
<random>
#include
<stdexcept>
#include
<stdexcept>
#include
<cassert>
#include
<cassert>
static
std
::
uniform_int_distribution
<
uint8_t
>
rand_byte
;
static
gnutls_digest_algorithm_t
get_dig_for_pub
(
gnutls_pubkey_t
pubkey
)
static
gnutls_digest_algorithm_t
get_dig_for_pub
(
gnutls_pubkey_t
pubkey
)
{
{
gnutls_digest_algorithm_t
dig
;
gnutls_digest_algorithm_t
dig
;
...
@@ -82,6 +85,87 @@ static gnutls_digest_algorithm_t get_dig(gnutls_x509_crt_t crt)
...
@@ -82,6 +85,87 @@ static gnutls_digest_algorithm_t get_dig(gnutls_x509_crt_t crt)
namespace
dht
{
namespace
dht
{
namespace
crypto
{
namespace
crypto
{
static
constexpr
std
::
array
<
size_t
,
3
>
AES_LENGTHS
{
128
/
8
,
192
/
8
,
256
/
8
};
size_t
aesKeySize
(
size_t
max
)
{
unsigned
aes_key_len
=
0
;
for
(
size_t
s
=
0
;
s
<
AES_LENGTHS
.
size
();
s
++
)
{
if
(
AES_LENGTHS
[
s
]
<=
max
)
aes_key_len
=
AES_LENGTHS
[
s
];
else
break
;
}
return
aes_key_len
;
}
bool
aesKeySizeGood
(
size_t
key_size
)
{
for
(
auto
&
i
:
AES_LENGTHS
)
if
(
key_size
==
i
)
return
true
;
return
false
;
}
#ifndef GCM_DIGEST_SIZE
#define GCM_DIGEST_SIZE GCM_BLOCK_SIZE
#endif
Blob
aesEncrypt
(
const
Blob
&
data
,
const
Blob
&
key
)
{
std
::
array
<
uint8_t
,
GCM_IV_SIZE
>
iv
;
{
crypto
::
random_device
rdev
;
std
::
generate_n
(
iv
.
begin
(),
iv
.
size
(),
std
::
bind
(
rand_byte
,
std
::
ref
(
rdev
)));
}
struct
gcm_aes_ctx
aes
;
gcm_aes_set_key
(
&
aes
,
key
.
size
(),
key
.
data
());
gcm_aes_set_iv
(
&
aes
,
iv
.
size
(),
iv
.
data
());
gcm_aes_update
(
&
aes
,
data
.
size
(),
data
.
data
());
Blob
ret
(
data
.
size
()
+
GCM_IV_SIZE
+
GCM_DIGEST_SIZE
);
std
::
copy
(
iv
.
begin
(),
iv
.
end
(),
ret
.
begin
());
gcm_aes_encrypt
(
&
aes
,
data
.
size
(),
ret
.
data
()
+
GCM_IV_SIZE
,
data
.
data
());
gcm_aes_digest
(
&
aes
,
GCM_DIGEST_SIZE
,
ret
.
data
()
+
GCM_IV_SIZE
+
data
.
size
());
return
ret
;
}
Blob
aesDecrypt
(
const
Blob
&
data
,
const
Blob
&
key
)
{
if
(
not
aesKeySizeGood
(
key
.
size
()))
throw
DecryptError
(
"Wrong key size"
);
if
(
data
.
size
()
<=
GCM_IV_SIZE
+
GCM_DIGEST_SIZE
)
throw
DecryptError
(
"Wrong data size"
);
std
::
array
<
uint8_t
,
GCM_DIGEST_SIZE
>
digest
;
struct
gcm_aes_ctx
aes
;
gcm_aes_set_key
(
&
aes
,
key
.
size
(),
key
.
data
());
gcm_aes_set_iv
(
&
aes
,
GCM_IV_SIZE
,
data
.
data
());
size_t
data_sz
=
data
.
size
()
-
GCM_IV_SIZE
-
GCM_DIGEST_SIZE
;
Blob
ret
(
data_sz
);
//gcm_aes_update(&aes, data_sz, data.data() + GCM_IV_SIZE);
gcm_aes_decrypt
(
&
aes
,
data_sz
,
ret
.
data
(),
data
.
data
()
+
GCM_IV_SIZE
);
//gcm_aes_digest(aes, GCM_DIGEST_SIZE, digest.data());
// TODO compute the proper digest directly from the decryption pass
Blob
ret_tmp
(
data_sz
);
struct
gcm_aes_ctx
aes_d
;
gcm_aes_set_key
(
&
aes_d
,
key
.
size
(),
key
.
data
());
gcm_aes_set_iv
(
&
aes_d
,
GCM_IV_SIZE
,
data
.
data
());
gcm_aes_update
(
&
aes_d
,
ret
.
size
()
,
ret
.
data
());
gcm_aes_encrypt
(
&
aes_d
,
ret
.
size
(),
ret_tmp
.
data
(),
ret
.
data
());
gcm_aes_digest
(
&
aes_d
,
GCM_DIGEST_SIZE
,
digest
.
data
());
if
(
not
std
::
equal
(
digest
.
begin
(),
digest
.
end
(),
data
.
end
()
-
GCM_DIGEST_SIZE
))
throw
DecryptError
(
"Can't decrypt data"
);
return
ret
;
}
PrivateKey
::
PrivateKey
()
PrivateKey
::
PrivateKey
()
{
{
#if GNUTLS_VERSION_NUMBER < 0x030300
#if GNUTLS_VERSION_NUMBER < 0x030300
...
@@ -194,6 +278,19 @@ PrivateKey::sign(const Blob& data) const
...
@@ -194,6 +278,19 @@ PrivateKey::sign(const Blob& data) const
return
ret
;
return
ret
;
}
}
Blob
PrivateKey
::
decryptBloc
(
const
uint8_t
*
src
,
size_t
src_size
)
const
{
const
gnutls_datum_t
dat
{(
uint8_t
*
)
src
,
(
unsigned
)
src_size
};
gnutls_datum_t
out
;
int
err
=
gnutls_privkey_decrypt_data
(
key
,
0
,
&
dat
,
&
out
);
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
DecryptError
(
std
::
string
(
"Can't decrypt data: "
)
+
gnutls_strerror
(
err
));
Blob
ret
{
out
.
data
,
out
.
data
+
out
.
size
};
gnutls_free
(
out
.
data
);
return
ret
;
}
Blob
Blob
PrivateKey
::
decrypt
(
const
Blob
&
cipher
)
const
PrivateKey
::
decrypt
(
const
Blob
&
cipher
)
const
{
{
...
@@ -208,20 +305,12 @@ PrivateKey::decrypt(const Blob& cipher) const
...
@@ -208,20 +305,12 @@ PrivateKey::decrypt(const Blob& cipher) const
throw
CryptoException
(
"Must be an RSA key"
);
throw
CryptoException
(
"Must be an RSA key"
);
unsigned
cypher_block_sz
=
key_len
/
8
;
unsigned
cypher_block_sz
=
key_len
/
8
;
if
(
cipher
.
size
()
%
cypher_block_sz
)
if
(
cipher
.
size
()
<
cypher_block_sz
)
throw
CryptoException
(
"Unexpected cipher length"
);
throw
DecryptError
(
"Unexpected cipher length"
);
else
if
(
cipher
.
size
()
==
cypher_block_sz
)
return
decryptBloc
(
cipher
.
data
(),
cypher_block_sz
);
Blob
ret
;
return
aesDecrypt
(
Blob
{
cipher
.
begin
()
+
cypher_block_sz
,
cipher
.
end
()},
decryptBloc
(
cipher
.
data
(),
cypher_block_sz
));
for
(
auto
cb
=
cipher
.
cbegin
(),
ce
=
cipher
.
cend
();
cb
<
ce
;
cb
+=
cypher_block_sz
)
{
const
gnutls_datum_t
dat
{(
uint8_t
*
)(
&
(
*
cb
)),
cypher_block_sz
};
gnutls_datum_t
out
;
int
err
=
gnutls_privkey_decrypt_data
(
key
,
0
,
&
dat
,
&
out
);
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
DecryptError
(
std
::
string
(
"Can't decrypt data: "
)
+
gnutls_strerror
(
err
));
ret
.
insert
(
ret
.
end
(),
out
.
data
,
out
.
data
+
out
.
size
);
gnutls_free
(
out
.
data
);
}
return
ret
;
}
}
Blob
Blob
...
@@ -321,6 +410,20 @@ PublicKey::checkSignature(const Blob& data, const Blob& signature) const {
...
@@ -321,6 +410,20 @@ PublicKey::checkSignature(const Blob& data, const Blob& signature) const {
return
rc
>=
0
;
return
rc
>=
0
;
}
}
void
PublicKey
::
encryptBloc
(
const
uint8_t
*
src
,
size_t
src_size
,
uint8_t
*
dst
,
size_t
dst_size
)
const
{
const
gnutls_datum_t
key_dat
{(
uint8_t
*
)
src
,
(
unsigned
)
src_size
};
gnutls_datum_t
encrypted
;
auto
err
=
gnutls_pubkey_encrypt_data
(
pk
,
0
,
&
key_dat
,
&
encrypted
);
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
CryptoException
(
std
::
string
(
"Can't encrypt data: "
)
+
gnutls_strerror
(
err
));
if
(
encrypted
.
size
!=
dst_size
)
throw
CryptoException
(
"Unexpected cypherblock size"
);
std
::
copy_n
(
encrypted
.
data
,
encrypted
.
size
,
dst
);
gnutls_free
(
encrypted
.
data
);
}
Blob
Blob
PublicKey
::
encrypt
(
const
Blob
&
data
)
const
PublicKey
::
encrypt
(
const
Blob
&
data
)
const
{
{
...
@@ -334,27 +437,30 @@ PublicKey::encrypt(const Blob& data) const
...
@@ -334,27 +437,30 @@ PublicKey::encrypt(const Blob& data) const
if
(
err
!=
GNUTLS_PK_RSA
)
if
(
err
!=
GNUTLS_PK_RSA
)
throw
CryptoException
(
"Must be an RSA key"
);
throw
CryptoException
(
"Must be an RSA key"
);
unsigned
max_block_sz
=
key_len
/
8
-
11
;
const
unsigned
max_block_sz
=
key_len
/
8
-
11
;
unsigned
cypher_block_sz
=
key_len
/
8
;
const
unsigned
cypher_block_sz
=
key_len
/
8
;
unsigned
block_num
=
data
.
empty
()
?
1
:
1
+
(
data
.
size
()
-
1
)
/
max_block_sz
;
if
(
data
.
size
()
<=
max_block_sz
)
{
Blob
ret
(
cypher_block_sz
);
encryptBloc
(
data
.
data
(),
data
.
size
(),
ret
.
data
(),
cypher_block_sz
);
return
ret
;
}
Blob
ret
;
unsigned
aes_key_sz
=
aesKeySize
(
max_block_sz
);
auto
eb
=
data
.
cbegin
();
if
(
aes_key_sz
==
0
)
auto
ee
=
data
.
cend
();
throw
CryptoException
(
"Key is not long enough for AES128"
);
for
(
unsigned
i
=
0
;
i
<
block_num
;
i
++
)
{
Blob
key
(
aes_key_sz
);
auto
blk_sz
=
std
::
min
<
unsigned
>
(
ee
-
eb
,
max_block_sz
);
{
const
gnutls_datum_t
dat
{(
uint8_t
*
)
&
(
*
eb
),
blk_sz
};
crypto
::
random_device
rdev
;
gnutls_datum_t
encrypted
;
std
::
generate_n
(
key
.
begin
(),
key
.
size
(),
std
::
bind
(
rand_byte
,
std
::
ref
(
rdev
)));
err
=
gnutls_pubkey_encrypt_data
(
pk
,
0
,
&
dat
,
&
encrypted
);
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
CryptoException
(
std
::
string
(
"Can't encrypt data: "
)
+
gnutls_strerror
(
err
));
if
(
encrypted
.
size
!=
cypher_block_sz
)
throw
CryptoException
(
"Unexpected cypherblock size"
);
ret
.
insert
(
ret
.
end
(),
encrypted
.
data
,
encrypted
.
data
+
encrypted
.
size
);
eb
+=
blk_sz
;
gnutls_free
(
encrypted
.
data
);
}
}
auto
data_encrypted
=
aesEncrypt
(
data
,
key
);
Blob
ret
;
ret
.
reserve
(
cypher_block_sz
+
data_encrypted
.
size
());
ret
.
resize
(
cypher_block_sz
);
encryptBloc
(
key
.
data
(),
key
.
size
(),
ret
.
data
(),
cypher_block_sz
);
ret
.
insert
(
ret
.
end
(),
data_encrypted
.
begin
(),
data_encrypted
.
end
());
return
ret
;
return
ret
;
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment