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
9b881d4e
Commit
9b881d4e
authored
6 years ago
by
Adrien Béraud
Browse files
Options
Downloads
Patches
Plain Diff
crypto: add initial certificate request support
parent
b4c3c2cb
No related branches found
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
include/opendht/crypto.h
+45
-8
45 additions, 8 deletions
include/opendht/crypto.h
src/crypto.cpp
+256
-97
256 additions, 97 deletions
src/crypto.cpp
tests/cryptotester.cpp
+28
-1
28 additions, 1 deletion
tests/cryptotester.cpp
tests/cryptotester.h
+5
-0
5 additions, 0 deletions
tests/cryptotester.h
with
334 additions
and
106 deletions
include/opendht/crypto.h
+
45
−
8
View file @
9b881d4e
...
@@ -66,7 +66,7 @@ using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certific
...
@@ -66,7 +66,7 @@ using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certific
*/
*/
struct
OPENDHT_PUBLIC
PublicKey
struct
OPENDHT_PUBLIC
PublicKey
{
{
PublicKey
()
{}
PublicKey
()
;
/**
/**
* Takes ownership of an existing gnutls_pubkey.
* Takes ownership of an existing gnutls_pubkey.
...
@@ -115,7 +115,9 @@ struct OPENDHT_PUBLIC PublicKey
...
@@ -115,7 +115,9 @@ struct OPENDHT_PUBLIC PublicKey
void
msgpack_unpack
(
msgpack
::
object
o
);
void
msgpack_unpack
(
msgpack
::
object
o
);
gnutls_pubkey_t
pk
{};
gnutls_digest_algorithm_t
getPreferredDigest
()
const
;
gnutls_pubkey_t
pk
{
nullptr
};
private
:
private
:
PublicKey
(
const
PublicKey
&
)
=
delete
;
PublicKey
(
const
PublicKey
&
)
=
delete
;
PublicKey
&
operator
=
(
const
PublicKey
&
)
=
delete
;
PublicKey
&
operator
=
(
const
PublicKey
&
)
=
delete
;
...
@@ -254,14 +256,48 @@ private:
...
@@ -254,14 +256,48 @@ private:
RevocationList
&
operator
=
(
const
RevocationList
&
)
=
delete
;
RevocationList
&
operator
=
(
const
RevocationList
&
)
=
delete
;
};
};
enum
class
NameType
{
UNKNOWN
=
0
,
RFC822
,
DNS
,
URI
,
IP
};
class
OPENDHT_PUBLIC
CertificateRequest
{
public:
CertificateRequest
();
CertificateRequest
(
const
uint8_t
*
data
,
size_t
size
);
CertificateRequest
(
const
Blob
&
data
)
:
CertificateRequest
(
data
.
data
(),
data
.
size
())
{}
CertificateRequest
(
CertificateRequest
&&
o
)
noexcept
:
request
(
std
::
move
(
o
.
request
))
{
o
.
request
=
nullptr
;
}
CertificateRequest
&
operator
=
(
CertificateRequest
&&
o
)
noexcept
;
~
CertificateRequest
();
void
setName
(
const
std
::
string
&
name
);
void
setUID
(
const
std
::
string
&
name
);
void
setAltName
(
NameType
type
,
const
std
::
string
&
name
);
std
::
string
getName
()
const
;
std
::
string
getUID
()
const
;
void
sign
(
const
PrivateKey
&
key
,
const
std
::
string
&
password
=
{});
bool
verify
()
const
;
Blob
pack
()
const
;
gnutls_x509_crq_t
get
()
const
{
return
request
;
}
private
:
CertificateRequest
(
const
CertificateRequest
&
o
)
=
delete
;
CertificateRequest
&
operator
=
(
const
CertificateRequest
&
o
)
=
delete
;
gnutls_x509_crq_t
request
{
nullptr
};
};
struct
OPENDHT_PUBLIC
Certificate
{
struct
OPENDHT_PUBLIC
Certificate
{
Certificate
()
{}
Certificate
()
noexcept
{}
/**
/**
* Take ownership of existing gnutls structure
* Take ownership of existing gnutls structure
*/
*/
Certificate
(
gnutls_x509_crt_t
crt
)
:
cert
(
crt
)
{}
Certificate
(
gnutls_x509_crt_t
crt
)
noexcept
:
cert
(
crt
)
{}
Certificate
(
Certificate
&&
o
)
noexcept
:
cert
(
o
.
cert
),
issuer
(
std
::
move
(
o
.
issuer
))
{
o
.
cert
=
nullptr
;
};
Certificate
(
Certificate
&&
o
)
noexcept
:
cert
(
o
.
cert
),
issuer
(
std
::
move
(
o
.
issuer
))
{
o
.
cert
=
nullptr
;
};
...
@@ -392,8 +428,6 @@ struct OPENDHT_PUBLIC Certificate {
...
@@ -392,8 +428,6 @@ struct OPENDHT_PUBLIC Certificate {
/** Read certificate issuer User ID (UID) */
/** Read certificate issuer User ID (UID) */
std
::
string
getIssuerUID
()
const
;
std
::
string
getIssuerUID
()
const
;
enum
class
NameType
{
UNKNOWN
=
0
,
RFC822
,
DNS
,
URI
,
IP
};
/** Read certificate alternative names */
/** Read certificate alternative names */
std
::
vector
<
std
::
pair
<
NameType
,
std
::
string
>>
getAltNames
()
const
;
std
::
vector
<
std
::
pair
<
NameType
,
std
::
string
>>
getAltNames
()
const
;
...
@@ -432,6 +466,7 @@ struct OPENDHT_PUBLIC Certificate {
...
@@ -432,6 +466,7 @@ struct OPENDHT_PUBLIC Certificate {
void
addRevocationList
(
std
::
shared_ptr
<
RevocationList
>
);
void
addRevocationList
(
std
::
shared_ptr
<
RevocationList
>
);
static
Certificate
generate
(
const
PrivateKey
&
key
,
const
std
::
string
&
name
=
"dhtnode"
,
const
Identity
&
ca
=
{},
bool
is_ca
=
false
);
static
Certificate
generate
(
const
PrivateKey
&
key
,
const
std
::
string
&
name
=
"dhtnode"
,
const
Identity
&
ca
=
{},
bool
is_ca
=
false
);
static
Certificate
generate
(
const
CertificateRequest
&
request
,
const
Identity
&
ca
);
gnutls_x509_crt_t
getCopy
()
const
{
gnutls_x509_crt_t
getCopy
()
const
{
if
(
not
cert
)
if
(
not
cert
)
...
@@ -472,7 +507,9 @@ struct OPENDHT_PUBLIC Certificate {
...
@@ -472,7 +507,9 @@ struct OPENDHT_PUBLIC Certificate {
return
{
crts
,
crls
};
return
{
crts
,
crls
};
}
}
gnutls_x509_crt_t
cert
{};
gnutls_digest_algorithm_t
getPreferredDigest
()
const
;
gnutls_x509_crt_t
cert
{
nullptr
};
std
::
shared_ptr
<
Certificate
>
issuer
{};
std
::
shared_ptr
<
Certificate
>
issuer
{};
private
:
private
:
Certificate
(
const
Certificate
&
)
=
delete
;
Certificate
(
const
Certificate
&
)
=
delete
;
...
@@ -513,7 +550,7 @@ struct OPENDHT_PUBLIC TrustList
...
@@ -513,7 +550,7 @@ struct OPENDHT_PUBLIC TrustList
private
:
private
:
TrustList
(
const
TrustList
&
o
)
=
delete
;
TrustList
(
const
TrustList
&
o
)
=
delete
;
TrustList
&
operator
=
(
const
TrustList
&
o
)
=
delete
;
TrustList
&
operator
=
(
const
TrustList
&
o
)
=
delete
;
gnutls_x509_trust_list_t
trust
;
gnutls_x509_trust_list_t
trust
{
nullptr
}
;
};
};
template
<
class
T
>
template
<
class
T
>
...
...
This diff is collapsed.
Click to expand it.
src/crypto.cpp
+
256
−
97
View file @
9b881d4e
...
@@ -40,31 +40,6 @@ static std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint
...
@@ -40,31 +40,6 @@ static std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint
static
std
::
uniform_int_distribution
<
uint8_t
>
rand_byte
;
static
std
::
uniform_int_distribution
<
uint8_t
>
rand_byte
;
#endif
#endif
static
gnutls_digest_algorithm_t
get_dig_for_pub
(
gnutls_pubkey_t
pubkey
)
{
gnutls_digest_algorithm_t
dig
;
int
result
=
gnutls_pubkey_get_preferred_hash_algorithm
(
pubkey
,
&
dig
,
nullptr
);
if
(
result
<
0
)
return
GNUTLS_DIG_UNKNOWN
;
return
dig
;
}
static
gnutls_digest_algorithm_t
get_dig
(
gnutls_x509_crt_t
crt
)
{
gnutls_pubkey_t
pubkey
;
gnutls_pubkey_init
(
&
pubkey
);
int
result
=
gnutls_pubkey_import_x509
(
pubkey
,
crt
,
0
);
if
(
result
<
0
)
{
gnutls_pubkey_deinit
(
pubkey
);
return
GNUTLS_DIG_UNKNOWN
;
}
gnutls_digest_algorithm_t
dig
=
get_dig_for_pub
(
pubkey
);
gnutls_pubkey_deinit
(
pubkey
);
return
dig
;
}
// support for GnuTLS < 3.4.
// support for GnuTLS < 3.4.
#if GNUTLS_VERSION_NUMBER < 0x030400
#if GNUTLS_VERSION_NUMBER < 0x030400
#define GNUTLS_PKCS_PKCS12_3DES GNUTLS_PKCS_USE_PKCS12_3DES
#define GNUTLS_PKCS_PKCS12_3DES GNUTLS_PKCS_USE_PKCS12_3DES
...
@@ -377,15 +352,19 @@ PrivateKey::serialize(const std::string& password) const
...
@@ -377,15 +352,19 @@ PrivateKey::serialize(const std::string& password) const
PublicKey
PublicKey
PrivateKey
::
getPublicKey
()
const
PrivateKey
::
getPublicKey
()
const
{
{
gnutls_pubkey_t
pk
;
PublicKey
pk
;
gnutls_pubkey_init
(
&
pk
);
if
(
auto
err
=
gnutls_pubkey_import_privkey
(
pk
.
pk
,
key
,
GNUTLS_KEY_KEY_CERT_SIGN
|
GNUTLS_KEY_CRL_SIGN
,
0
))
PublicKey
pk_ret
{
pk
};
throw
CryptoException
(
std
::
string
(
"Can't retreive public key: "
)
+
gnutls_strerror
(
err
));
if
(
gnutls_pubkey_import_privkey
(
pk
,
key
,
GNUTLS_KEY_KEY_CERT_SIGN
|
GNUTLS_KEY_CRL_SIGN
,
0
)
!=
GNUTLS_E_SUCCESS
)
return
pk
;
return
{};
}
return
pk_ret
;
PublicKey
::
PublicKey
()
{
if
(
auto
err
=
gnutls_pubkey_init
(
&
pk
))
throw
CryptoException
(
std
::
string
(
"Can't initialize public key: "
)
+
gnutls_strerror
(
err
));
}
}
PublicKey
::
PublicKey
(
const
Blob
&
dat
)
PublicKey
::
PublicKey
(
const
Blob
&
dat
)
:
PublicKey
()
{
{
unpack
(
dat
.
data
(),
dat
.
size
());
unpack
(
dat
.
data
(),
dat
.
size
());
}
}
...
@@ -415,8 +394,7 @@ PublicKey::pack(Blob& b) const
...
@@ -415,8 +394,7 @@ PublicKey::pack(Blob& b) const
throw
CryptoException
(
std
::
string
(
"Could not export public key: null key"
));
throw
CryptoException
(
std
::
string
(
"Could not export public key: null key"
));
std
::
vector
<
uint8_t
>
tmp
(
2048
);
std
::
vector
<
uint8_t
>
tmp
(
2048
);
size_t
sz
=
tmp
.
size
();
size_t
sz
=
tmp
.
size
();
int
err
=
gnutls_pubkey_export
(
pk
,
GNUTLS_X509_FMT_DER
,
tmp
.
data
(),
&
sz
);
if
(
int
err
=
gnutls_pubkey_export
(
pk
,
GNUTLS_X509_FMT_DER
,
tmp
.
data
(),
&
sz
))
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
CryptoException
(
std
::
string
(
"Could not export public key: "
)
+
gnutls_strerror
(
err
));
throw
CryptoException
(
std
::
string
(
"Could not export public key: "
)
+
gnutls_strerror
(
err
));
tmp
.
resize
(
sz
);
tmp
.
resize
(
sz
);
b
.
insert
(
b
.
end
(),
tmp
.
begin
(),
tmp
.
end
());
b
.
insert
(
b
.
end
(),
tmp
.
begin
(),
tmp
.
end
());
...
@@ -425,9 +403,6 @@ PublicKey::pack(Blob& b) const
...
@@ -425,9 +403,6 @@ PublicKey::pack(Blob& b) const
void
void
PublicKey
::
unpack
(
const
uint8_t
*
data
,
size_t
data_size
)
PublicKey
::
unpack
(
const
uint8_t
*
data
,
size_t
data_size
)
{
{
if
(
pk
)
gnutls_pubkey_deinit
(
pk
);
gnutls_pubkey_init
(
&
pk
);
const
gnutls_datum_t
dat
{(
uint8_t
*
)
data
,
(
unsigned
)
data_size
};
const
gnutls_datum_t
dat
{(
uint8_t
*
)
data
,
(
unsigned
)
data_size
};
int
err
=
gnutls_pubkey_import
(
pk
,
&
dat
,
GNUTLS_X509_FMT_PEM
);
int
err
=
gnutls_pubkey_import
(
pk
,
&
dat
,
GNUTLS_X509_FMT_PEM
);
if
(
err
!=
GNUTLS_E_SUCCESS
)
if
(
err
!=
GNUTLS_E_SUCCESS
)
...
@@ -446,11 +421,10 @@ PublicKey::toString() const
...
@@ -446,11 +421,10 @@ PublicKey::toString() const
int
err
=
gnutls_pubkey_export
(
pk
,
GNUTLS_X509_FMT_PEM
,
(
void
*
)
ret
.
data
(),
&
sz
);
int
err
=
gnutls_pubkey_export
(
pk
,
GNUTLS_X509_FMT_PEM
,
(
void
*
)
ret
.
data
(),
&
sz
);
if
(
err
==
GNUTLS_E_SHORT_MEMORY_BUFFER
)
{
if
(
err
==
GNUTLS_E_SHORT_MEMORY_BUFFER
)
{
ret
.
resize
(
sz
);
ret
.
resize
(
sz
);
int
err
=
gnutls_pubkey_export
(
pk
,
GNUTLS_X509_FMT_PEM
,
(
void
*
)
ret
.
data
(),
&
sz
);
err
=
gnutls_pubkey_export
(
pk
,
GNUTLS_X509_FMT_PEM
,
(
void
*
)
ret
.
data
(),
&
sz
);
}
if
(
err
!=
GNUTLS_E_SUCCESS
)
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
CryptoException
(
std
::
string
(
"Could not print public key: "
)
+
gnutls_strerror
(
err
));
throw
CryptoException
(
std
::
string
(
"Could not print public key: "
)
+
gnutls_strerror
(
err
));
}
else
if
(
err
!=
GNUTLS_E_SUCCESS
)
throw
CryptoException
(
std
::
string
(
"Could not print public key: "
)
+
gnutls_strerror
(
err
));
return
ret
;
return
ret
;
}
}
...
@@ -572,6 +546,179 @@ PublicKey::getLongId() const
...
@@ -572,6 +546,179 @@ PublicKey::getLongId() const
#endif
#endif
}
}
gnutls_digest_algorithm_t
PublicKey
::
getPreferredDigest
()
const
{
gnutls_digest_algorithm_t
dig
;
int
result
=
gnutls_pubkey_get_preferred_hash_algorithm
(
pk
,
&
dig
,
nullptr
);
if
(
result
<
0
)
return
GNUTLS_DIG_UNKNOWN
;
return
dig
;
}
// Certificate Request
static
NameType
typeFromGnuTLS
(
gnutls_x509_subject_alt_name_t
type
)
{
switch
(
type
)
{
case
GNUTLS_SAN_DNSNAME
:
return
NameType
::
DNS
;
case
GNUTLS_SAN_RFC822NAME
:
return
NameType
::
RFC822
;
case
GNUTLS_SAN_URI
:
return
NameType
::
URI
;
case
GNUTLS_SAN_IPADDRESS
:
return
NameType
::
IP
;
default:
return
NameType
::
UNKNOWN
;
}
}
static
gnutls_x509_subject_alt_name_t
GnuTLSFromType
(
NameType
type
)
{
switch
(
type
)
{
case
NameType
::
DNS
:
return
GNUTLS_SAN_DNSNAME
;
case
NameType
::
RFC822
:
return
GNUTLS_SAN_RFC822NAME
;
case
NameType
::
URI
:
return
GNUTLS_SAN_URI
;
case
NameType
::
IP
:
return
GNUTLS_SAN_IPADDRESS
;
default:
return
(
gnutls_x509_subject_alt_name_t
)
0
;
}
}
static
std
::
string
getDN
(
gnutls_x509_crq_t
request
,
const
char
*
oid
)
{
std
::
string
dn
;
dn
.
resize
(
512
);
size_t
dn_sz
=
dn
.
size
();
int
ret
=
gnutls_x509_crq_get_dn_by_oid
(
request
,
oid
,
0
,
0
,
&
(
*
dn
.
begin
()),
&
dn_sz
);
if
(
ret
!=
GNUTLS_E_SUCCESS
)
return
{};
dn
.
resize
(
dn_sz
);
return
dn
;
}
CertificateRequest
::
CertificateRequest
()
{
if
(
auto
err
=
gnutls_x509_crq_init
(
&
request
))
throw
CryptoException
(
std
::
string
(
"Can't initialize certificate request: "
)
+
gnutls_strerror
(
err
));
}
CertificateRequest
::
CertificateRequest
(
const
uint8_t
*
data
,
size_t
size
)
:
CertificateRequest
()
{
const
gnutls_datum_t
dat
{(
uint8_t
*
)
data
,
(
unsigned
)
size
};
if
(
auto
err
=
gnutls_x509_crq_import
(
request
,
&
dat
,
GNUTLS_X509_FMT_PEM
))
throw
CryptoException
(
std
::
string
(
"Can't import certificate request: "
)
+
gnutls_strerror
(
err
));
}
CertificateRequest
::~
CertificateRequest
()
{
if
(
request
)
{
gnutls_x509_crq_deinit
(
request
);
request
=
nullptr
;
}
}
CertificateRequest
&
CertificateRequest
::
operator
=
(
CertificateRequest
&&
o
)
noexcept
{
if
(
request
)
gnutls_x509_crq_deinit
(
request
);
request
=
o
.
request
;
o
.
request
=
nullptr
;
return
*
this
;
}
void
CertificateRequest
::
setAltName
(
NameType
type
,
const
std
::
string
&
name
)
{
gnutls_x509_crq_set_subject_alt_name
(
request
,
GnuTLSFromType
(
type
),
name
.
data
(),
name
.
size
(),
0
);
}
void
CertificateRequest
::
setName
(
const
std
::
string
&
name
)
{
gnutls_x509_crq_set_dn_by_oid
(
request
,
GNUTLS_OID_X520_COMMON_NAME
,
0
,
name
.
data
(),
name
.
length
());
}
std
::
string
CertificateRequest
::
getName
()
const
{
return
getDN
(
request
,
GNUTLS_OID_X520_COMMON_NAME
);
}
std
::
string
CertificateRequest
::
getUID
()
const
{
return
getDN
(
request
,
GNUTLS_OID_LDAP_UID
);
}
void
CertificateRequest
::
setUID
(
const
std
::
string
&
uid
)
{
gnutls_x509_crq_set_dn_by_oid
(
request
,
GNUTLS_OID_LDAP_UID
,
0
,
uid
.
data
(),
uid
.
length
());
}
void
CertificateRequest
::
sign
(
const
PrivateKey
&
key
,
const
std
::
string
&
password
)
{
gnutls_x509_crq_set_version
(
request
,
1
);
if
(
not
password
.
empty
())
gnutls_x509_crq_set_challenge_password
(
request
,
password
.
c_str
());
if
(
auto
err
=
gnutls_x509_crq_set_key
(
request
,
key
.
x509_key
))
throw
CryptoException
(
std
::
string
(
"Can't set certificate request key: "
)
+
gnutls_strerror
(
err
));
#if GNUTLS_VERSION_NUMBER < 0x030601
if
(
auto
err
=
gnutls_x509_crq_privkey_sign
(
request
,
key
.
key
,
key
.
getPublicKey
().
getPreferredDigest
(),
0
))
throw
CryptoException
(
std
::
string
(
"Can't sign certificate request: "
)
+
gnutls_strerror
(
err
));
#else
if
(
auto
err
=
gnutls_x509_crq_privkey_sign
(
request
,
key
.
key
,
GNUTLS_DIG_UNKNOWN
,
0
))
throw
CryptoException
(
std
::
string
(
"Can't sign certificate request: "
)
+
gnutls_strerror
(
err
));
#endif
}
bool
CertificateRequest
::
verify
()
const
{
return
gnutls_x509_crq_verify
(
request
,
0
)
>=
0
;
}
Blob
CertificateRequest
::
pack
()
const
{
gnutls_datum_t
dat
{
nullptr
,
0
};
if
(
auto
err
=
gnutls_x509_crq_export2
(
request
,
GNUTLS_X509_FMT_PEM
,
&
dat
))
throw
CryptoException
(
std
::
string
(
"Can't export certificate request: "
)
+
gnutls_strerror
(
err
));
Blob
ret
(
dat
.
data
,
dat
.
data
+
dat
.
size
);
gnutls_free
(
dat
.
data
);
return
ret
;
}
// Certificate
static
std
::
string
getDN
(
gnutls_x509_crt_t
cert
,
const
char
*
oid
,
bool
issuer
=
false
)
{
std
::
string
dn
;
dn
.
resize
(
512
);
size_t
dn_sz
=
dn
.
size
();
int
ret
=
issuer
?
gnutls_x509_crt_get_issuer_dn_by_oid
(
cert
,
oid
,
0
,
0
,
&
(
*
dn
.
begin
()),
&
dn_sz
)
:
gnutls_x509_crt_get_dn_by_oid
(
cert
,
oid
,
0
,
0
,
&
(
*
dn
.
begin
()),
&
dn_sz
);
if
(
ret
!=
GNUTLS_E_SUCCESS
)
return
{};
dn
.
resize
(
dn_sz
);
return
dn
;
}
Certificate
::
Certificate
(
const
Blob
&
certData
)
Certificate
::
Certificate
(
const
Blob
&
certData
)
{
{
unpack
(
certData
.
data
(),
certData
.
size
());
unpack
(
certData
.
data
(),
certData
.
size
());
...
@@ -656,11 +803,9 @@ Certificate::~Certificate()
...
@@ -656,11 +803,9 @@ Certificate::~Certificate()
PublicKey
PublicKey
Certificate
::
getPublicKey
()
const
Certificate
::
getPublicKey
()
const
{
{
gnutls_pubkey_t
pk
;
PublicKey
pk_ret
;
gnutls_pubkey_init
(
&
pk
);
if
(
auto
err
=
gnutls_pubkey_import_x509
(
pk_ret
.
pk
,
cert
,
0
))
PublicKey
pk_ret
(
pk
);
throw
CryptoException
(
std
::
string
(
"Can't get certificate public key: "
)
+
gnutls_strerror
(
err
));
if
(
gnutls_pubkey_import_x509
(
pk
,
cert
,
0
)
!=
GNUTLS_E_SUCCESS
)
return
{};
return
pk_ret
;
return
pk_ret
;
}
}
...
@@ -696,21 +841,6 @@ Certificate::getLongId() const
...
@@ -696,21 +841,6 @@ Certificate::getLongId() const
#endif
#endif
}
}
static
std
::
string
getDN
(
gnutls_x509_crt_t
cert
,
const
char
*
oid
,
bool
issuer
=
false
)
{
std
::
string
dn
;
dn
.
resize
(
512
);
size_t
dn_sz
=
dn
.
size
();
int
ret
=
issuer
?
gnutls_x509_crt_get_issuer_dn_by_oid
(
cert
,
oid
,
0
,
0
,
&
(
*
dn
.
begin
()),
&
dn_sz
)
:
gnutls_x509_crt_get_dn_by_oid
(
cert
,
oid
,
0
,
0
,
&
(
*
dn
.
begin
()),
&
dn_sz
);
if
(
ret
!=
GNUTLS_E_SUCCESS
)
return
{};
dn
.
resize
(
dn_sz
);
return
dn
;
}
std
::
string
std
::
string
Certificate
::
getName
()
const
Certificate
::
getName
()
const
{
{
...
@@ -735,24 +865,7 @@ Certificate::getIssuerUID() const
...
@@ -735,24 +865,7 @@ Certificate::getIssuerUID() const
return
getDN
(
cert
,
GNUTLS_OID_LDAP_UID
,
true
);
return
getDN
(
cert
,
GNUTLS_OID_LDAP_UID
,
true
);
}
}
static
Certificate
::
NameType
std
::
vector
<
std
::
pair
<
NameType
,
std
::
string
>>
typeFromGnuTLS
(
gnutls_x509_subject_alt_name_t
type
)
{
switch
(
type
)
{
case
GNUTLS_SAN_DNSNAME
:
return
Certificate
::
NameType
::
DNS
;
case
GNUTLS_SAN_RFC822NAME
:
return
Certificate
::
NameType
::
RFC822
;
case
GNUTLS_SAN_URI
:
return
Certificate
::
NameType
::
URI
;
case
GNUTLS_SAN_IPADDRESS
:
return
Certificate
::
NameType
::
IP
;
default:
return
Certificate
::
NameType
::
UNKNOWN
;
}
}
std
::
vector
<
std
::
pair
<
Certificate
::
NameType
,
std
::
string
>>
Certificate
::
getAltNames
()
const
Certificate
::
getAltNames
()
const
{
{
std
::
vector
<
std
::
pair
<
NameType
,
std
::
string
>>
names
;
std
::
vector
<
std
::
pair
<
NameType
,
std
::
string
>>
names
;
...
@@ -867,6 +980,14 @@ Certificate::getExpiration() const
...
@@ -867,6 +980,14 @@ Certificate::getExpiration() const
return
std
::
chrono
::
system_clock
::
from_time_t
(
t
);
return
std
::
chrono
::
system_clock
::
from_time_t
(
t
);
}
}
gnutls_digest_algorithm_t
Certificate
::
getPreferredDigest
()
const
{
return
getPublicKey
().
getPreferredDigest
();
}
// PrivateKey
PrivateKey
PrivateKey
PrivateKey
::
generate
(
unsigned
key_length
)
PrivateKey
::
generate
(
unsigned
key_length
)
{
{
...
@@ -922,6 +1043,27 @@ generateEcIdentity(const std::string& name, const Identity& ca) {
...
@@ -922,6 +1043,27 @@ generateEcIdentity(const std::string& name, const Identity& ca) {
return
generateEcIdentity
(
name
,
ca
,
!
ca
.
first
||
!
ca
.
second
);
return
generateEcIdentity
(
name
,
ca
,
!
ca
.
first
||
!
ca
.
second
);
}
}
void
setValidityPeriod
(
gnutls_x509_crt_t
cert
,
int64_t
validity
)
{
int64_t
now
=
time
(
nullptr
);
/* 2038 bug: don't allow time wrap */
auto
boundTime
=
[](
int64_t
t
)
->
time_t
{
return
std
::
min
<
int64_t
>
(
t
,
std
::
numeric_limits
<
time_t
>::
max
());
};
gnutls_x509_crt_set_activation_time
(
cert
,
boundTime
(
now
));
gnutls_x509_crt_set_expiration_time
(
cert
,
boundTime
(
now
+
validity
));
}
void
setRandomSerial
(
gnutls_x509_crt_t
cert
)
{
random_device
rdev
;
std
::
uniform_int_distribution
<
uint64_t
>
dist
{};
uint64_t
cert_serial
=
dist
(
rdev
);
gnutls_x509_crt_set_serial
(
cert
,
&
cert_serial
,
sizeof
(
cert_serial
));
}
Certificate
Certificate
Certificate
::
generate
(
const
PrivateKey
&
key
,
const
std
::
string
&
name
,
const
Identity
&
ca
,
bool
is_ca
)
Certificate
::
generate
(
const
PrivateKey
&
key
,
const
std
::
string
&
name
,
const
Identity
&
ca
,
bool
is_ca
)
{
{
...
@@ -930,13 +1072,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
...
@@ -930,13 +1072,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
return
{};
return
{};
Certificate
ret
{
cert
};
Certificate
ret
{
cert
};
int64_t
now
=
time
(
nullptr
);
setValidityPeriod
(
cert
,
10
*
365
*
24
*
60
*
60
);
/* 2038 bug: don't allow time wrap */
auto
boundTime
=
[](
int64_t
t
)
->
time_t
{
return
std
::
min
<
int64_t
>
(
t
,
std
::
numeric_limits
<
time_t
>::
max
());
};
gnutls_x509_crt_set_activation_time
(
cert
,
boundTime
(
now
));
gnutls_x509_crt_set_expiration_time
(
cert
,
boundTime
(
now
+
(
10
*
365
*
24
*
60
*
60
)));
if
(
gnutls_x509_crt_set_key
(
cert
,
key
.
x509_key
)
!=
GNUTLS_E_SUCCESS
)
{
if
(
gnutls_x509_crt_set_key
(
cert
,
key
.
x509_key
)
!=
GNUTLS_E_SUCCESS
)
{
std
::
cerr
<<
"Error when setting certificate key"
<<
std
::
endl
;
std
::
cerr
<<
"Error when setting certificate key"
<<
std
::
endl
;
return
{};
return
{};
...
@@ -947,19 +1083,15 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
...
@@ -947,19 +1083,15 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
}
}
// TODO: compute the subject key using the recommended RFC method
// TODO: compute the subject key using the recommended RFC method
auto
pk_id
=
key
.
getPublicKey
().
getId
();
auto
pk
=
key
.
getPublicKey
();
auto
pk_id
=
pk
.
getId
();
const
std
::
string
uid_str
=
pk_id
.
toString
();
const
std
::
string
uid_str
=
pk_id
.
toString
();
gnutls_x509_crt_set_subject_key_id
(
cert
,
&
pk_id
,
sizeof
(
pk_id
));
gnutls_x509_crt_set_subject_key_id
(
cert
,
&
pk_id
,
sizeof
(
pk_id
));
gnutls_x509_crt_set_dn_by_oid
(
cert
,
GNUTLS_OID_X520_COMMON_NAME
,
0
,
name
.
data
(),
name
.
length
());
gnutls_x509_crt_set_dn_by_oid
(
cert
,
GNUTLS_OID_X520_COMMON_NAME
,
0
,
name
.
data
(),
name
.
length
());
gnutls_x509_crt_set_dn_by_oid
(
cert
,
GNUTLS_OID_LDAP_UID
,
0
,
uid_str
.
data
(),
uid_str
.
length
());
gnutls_x509_crt_set_dn_by_oid
(
cert
,
GNUTLS_OID_LDAP_UID
,
0
,
uid_str
.
data
(),
uid_str
.
length
());
{
setRandomSerial
(
cert
);
random_device
rdev
;
std
::
uniform_int_distribution
<
uint64_t
>
dist
{};
uint64_t
cert_serial
=
dist
(
rdev
);
gnutls_x509_crt_set_serial
(
cert
,
&
cert_serial
,
sizeof
(
cert_serial
));
}
unsigned
key_usage
=
0
;
unsigned
key_usage
=
0
;
if
(
is_ca
)
{
if
(
is_ca
)
{
...
@@ -975,15 +1107,13 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
...
@@ -975,15 +1107,13 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
// Signing certificate must be CA.
// Signing certificate must be CA.
return
{};
return
{};
}
}
//if (gnutls_x509_crt_sign2(cert, ca.second->cert, ca.first->x509_key, get_dig(cert), 0) != GNUTLS_E_SUCCESS) {
if
(
gnutls_x509_crt_privkey_sign
(
cert
,
ca
.
second
->
cert
,
ca
.
first
->
key
,
pk
.
getPreferredDigest
(),
0
)
!=
GNUTLS_E_SUCCESS
)
{
if
(
gnutls_x509_crt_privkey_sign
(
cert
,
ca
.
second
->
cert
,
ca
.
first
->
key
,
get_dig
(
cert
),
0
)
!=
GNUTLS_E_SUCCESS
)
{
std
::
cerr
<<
"Error when signing certificate"
<<
std
::
endl
;
std
::
cerr
<<
"Error when signing certificate"
<<
std
::
endl
;
return
{};
return
{};
}
}
ret
.
issuer
=
ca
.
second
;
ret
.
issuer
=
ca
.
second
;
}
else
{
}
else
{
//if (gnutls_x509_crt_sign2(cert, cert, key, get_dig(cert), 0) != GNUTLS_E_SUCCESS) {
if
(
gnutls_x509_crt_privkey_sign
(
cert
,
cert
,
key
.
key
,
pk
.
getPreferredDigest
(),
0
)
!=
GNUTLS_E_SUCCESS
)
{
if
(
gnutls_x509_crt_privkey_sign
(
cert
,
cert
,
key
.
key
,
get_dig
(
cert
),
0
)
!=
GNUTLS_E_SUCCESS
)
{
std
::
cerr
<<
"Error when signing certificate"
<<
std
::
endl
;
std
::
cerr
<<
"Error when signing certificate"
<<
std
::
endl
;
return
{};
return
{};
}
}
...
@@ -992,6 +1122,31 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
...
@@ -992,6 +1122,31 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
return
ret
.
getPacked
();
return
ret
.
getPacked
();
}
}
Certificate
Certificate
::
generate
(
const
CertificateRequest
&
request
,
const
Identity
&
ca
)
{
gnutls_x509_crt_t
cert
;
if
(
auto
err
=
gnutls_x509_crt_init
(
&
cert
))
throw
CryptoException
(
std
::
string
(
"Can't initialize certificate: "
)
+
gnutls_strerror
(
err
));
Certificate
ret
{
cert
};
if
(
auto
err
=
gnutls_x509_crt_set_crq
(
cert
,
request
.
get
()))
throw
CryptoException
(
std
::
string
(
"Can't initialize certificate: "
)
+
gnutls_strerror
(
err
));
if
(
auto
err
=
gnutls_x509_crt_set_version
(
cert
,
3
))
{
throw
CryptoException
(
std
::
string
(
"Can't set certificate version: "
)
+
gnutls_strerror
(
err
));
}
setValidityPeriod
(
cert
,
10
*
365
*
24
*
60
*
60
);
setRandomSerial
(
cert
);
if
(
auto
err
=
gnutls_x509_crt_privkey_sign
(
cert
,
ca
.
second
->
cert
,
ca
.
first
->
key
,
ca
.
second
->
getPreferredDigest
(),
0
))
{
throw
CryptoException
(
std
::
string
(
"Can't sign certificate: "
)
+
gnutls_strerror
(
err
));
}
ret
.
issuer
=
ca
.
second
;
return
ret
.
getPacked
();
}
std
::
vector
<
std
::
shared_ptr
<
RevocationList
>>
std
::
vector
<
std
::
shared_ptr
<
RevocationList
>>
Certificate
::
getRevocationLists
()
const
Certificate
::
getRevocationLists
()
const
{
{
...
@@ -1002,6 +1157,8 @@ Certificate::getRevocationLists() const
...
@@ -1002,6 +1157,8 @@ Certificate::getRevocationLists() const
return
ret
;
return
ret
;
}
}
// RevocationList
RevocationList
::
RevocationList
()
RevocationList
::
RevocationList
()
{
{
gnutls_x509_crl_init
(
&
crl
);
gnutls_x509_crl_init
(
&
crl
);
...
@@ -1219,6 +1376,8 @@ RevocationList::toString() const
...
@@ -1219,6 +1376,8 @@ RevocationList::toString() const
return
ret
;
return
ret
;
}
}
// TrustList
TrustList
::
TrustList
()
{
TrustList
::
TrustList
()
{
gnutls_x509_trust_list_init
(
&
trust
,
0
);
gnutls_x509_trust_list_init
(
&
trust
,
0
);
}
}
...
...
This diff is collapsed.
Click to expand it.
tests/cryptotester.cpp
+
28
−
1
View file @
9b881d4e
...
@@ -54,7 +54,6 @@ CryptoTester::testCertificateRevocation()
...
@@ -54,7 +54,6 @@ CryptoTester::testCertificateRevocation()
auto
device11
=
dht
::
crypto
::
generateIdentity
(
"dev11"
,
account1
);
auto
device11
=
dht
::
crypto
::
generateIdentity
(
"dev11"
,
account1
);
auto
device12
=
dht
::
crypto
::
generateIdentity
(
"dev12"
,
account1
);
auto
device12
=
dht
::
crypto
::
generateIdentity
(
"dev12"
,
account1
);
dht
::
crypto
::
TrustList
list
;
dht
::
crypto
::
TrustList
list
;
list
.
add
(
*
ca1
.
second
);
list
.
add
(
*
ca1
.
second
);
auto
v
=
list
.
verify
(
*
account1
.
second
);
auto
v
=
list
.
verify
(
*
account1
.
second
);
...
@@ -83,6 +82,34 @@ CryptoTester::testCertificateRevocation()
...
@@ -83,6 +82,34 @@ CryptoTester::testCertificateRevocation()
CPPUNIT_ASSERT_MESSAGE
(
v
.
toString
(),
v
);
CPPUNIT_ASSERT_MESSAGE
(
v
.
toString
(),
v
);
}
}
void
CryptoTester
::
testCertificateRequest
()
{
// Generate CA
auto
ca
=
dht
::
crypto
::
generateIdentity
(
"Test CA"
);
// Generate signed request
auto
deviceKey
=
dht
::
crypto
::
PrivateKey
::
generate
();
auto
request
=
dht
::
crypto
::
CertificateRequest
();
request
.
setName
(
"Test Device"
);
request
.
sign
(
deviceKey
);
// Export/import request
auto
importedRequest
=
dht
::
crypto
::
CertificateRequest
(
request
.
pack
());
CPPUNIT_ASSERT
(
importedRequest
.
verify
());
// Generate/sign certificate from request
auto
signedCert
=
dht
::
crypto
::
Certificate
::
generate
(
request
,
ca
);
CPPUNIT_ASSERT_EQUAL
(
ca
.
second
->
getName
(),
signedCert
.
getIssuerName
());
CPPUNIT_ASSERT_EQUAL
(
request
.
getName
(),
signedCert
.
getName
());
// Check generated certificate
dht
::
crypto
::
TrustList
list
;
list
.
add
(
*
ca
.
second
);
auto
v
=
list
.
verify
(
signedCert
);
CPPUNIT_ASSERT_MESSAGE
(
v
.
toString
(),
v
);
}
void
void
CryptoTester
::
tearDown
()
{
CryptoTester
::
tearDown
()
{
...
...
This diff is collapsed.
Click to expand it.
tests/cryptotester.h
+
5
−
0
View file @
9b881d4e
...
@@ -29,6 +29,7 @@ class CryptoTester : public CppUnit::TestFixture {
...
@@ -29,6 +29,7 @@ class CryptoTester : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE
(
CryptoTester
);
CPPUNIT_TEST_SUITE
(
CryptoTester
);
CPPUNIT_TEST
(
testSignatureEncryption
);
CPPUNIT_TEST
(
testSignatureEncryption
);
CPPUNIT_TEST
(
testCertificateRevocation
);
CPPUNIT_TEST
(
testCertificateRevocation
);
CPPUNIT_TEST
(
testCertificateRequest
);
CPPUNIT_TEST_SUITE_END
();
CPPUNIT_TEST_SUITE_END
();
public:
public:
...
@@ -48,6 +49,10 @@ class CryptoTester : public CppUnit::TestFixture {
...
@@ -48,6 +49,10 @@ class CryptoTester : public CppUnit::TestFixture {
* Test certificate generation, validation and revocation
* Test certificate generation, validation and revocation
*/
*/
void
testCertificateRevocation
();
void
testCertificateRevocation
();
/**
* Test certificate requests
*/
void
testCertificateRequest
();
};
};
}
// namespace test
}
// namespace test
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