-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1717f8c
commit bfcf205
Showing
6 changed files
with
373 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
.. hazmat:: | ||
|
||
Ed25519 signing | ||
=============== | ||
|
||
.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed25519 | ||
|
||
|
||
Ed25519 is a signing algorithm using `EdDSA`_ and `Curve25519`_. If you do not | ||
have legacy interoperability concerns then you should strongly consider using | ||
this signature algorithm. | ||
|
||
|
||
Signing & Verification | ||
~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. doctest:: | ||
|
||
>>> from cryptography.hazmat.backends import default_backend | ||
>>> from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey | ||
>>> private_key = Ed25519PrivateKey.generate() | ||
>>> signature = private_key.sign(b"my authenticated message") | ||
>>> public_key = private_key.public_key() | ||
>>> # Raises InvalidSignature if verification fails | ||
>>> public_key.verify(signature, b"my authenticated message") | ||
|
||
Key interfaces | ||
~~~~~~~~~~~~~~ | ||
|
||
.. class:: Ed25519PrivateKey | ||
|
||
.. versionadded:: 2.4 | ||
|
||
.. classmethod:: generate() | ||
|
||
Generate an Ed25519 private key. | ||
|
||
:returns: :class:`Ed25519PrivateKey` | ||
|
||
.. method:: public_key() | ||
|
||
:returns: :class:`Ed25519PublicKey` | ||
|
||
.. method:: sign(data) | ||
|
||
:param bytes data: The data to sign. | ||
|
||
:returns bytes: The 64 byte signature. | ||
|
||
.. class:: Ed25519PublicKey | ||
|
||
.. versionadded:: 2.4 | ||
|
||
.. classmethod:: from_public_bytes(data) | ||
|
||
:param bytes data: 32 byte public key. | ||
|
||
:returns: :class:`Ed25519PublicKey` | ||
|
||
.. method:: public_bytes() | ||
|
||
:returns bytes: The raw bytes of the public key. | ||
|
||
.. method:: verify(signature, data) | ||
|
||
:param bytes signature: The signature to verify. | ||
|
||
:param bytes data: The data to verify. | ||
|
||
:raises cryptography.exceptions.InvalidSignature: Raised when the | ||
signature cannot be verified. | ||
|
||
|
||
|
||
.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA | ||
.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ private key is able to decrypt it. | |
|
||
x25519 | ||
ec | ||
ed25519 | ||
rsa | ||
dh | ||
dsa | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# This file is dual licensed under the terms of the Apache License, Version | ||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository | ||
# for complete details. | ||
|
||
from __future__ import absolute_import, division, print_function | ||
|
||
from cryptography import exceptions, utils | ||
from cryptography.hazmat.primitives.asymmetric.ed25519 import ( | ||
Ed25519PrivateKey, Ed25519PublicKey | ||
) | ||
|
||
|
||
@utils.register_interface(Ed25519PublicKey) | ||
class _Ed25519PublicKey(object): | ||
def __init__(self, backend, evp_pkey): | ||
self._backend = backend | ||
self._evp_pkey = evp_pkey | ||
|
||
def public_bytes(self): | ||
bio = self._backend._create_mem_bio_gc() | ||
res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey) | ||
self._backend.openssl_assert(res == 1) | ||
asn1 = self._backend._read_mem_bio(bio) | ||
# We serialize to the ASN.1 structure defined in | ||
# https://tools.ietf.org/html/draft-ietf-curdle-pkix-03. and | ||
# then take the last 32 bytes, which are the actual key. | ||
return asn1[-32:] | ||
|
||
def verify(self, signature, data): | ||
evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() | ||
self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) | ||
evp_md_ctx = self._backend._ffi.gc( | ||
evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free | ||
) | ||
res = self._backend._lib.EVP_DigestVerifyInit( | ||
evp_md_ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, | ||
self._backend._ffi.NULL, self._evp_pkey | ||
) | ||
self._backend.openssl_assert(res == 1) | ||
res = self._backend._lib.EVP_DigestVerify( | ||
evp_md_ctx, signature, len(signature), data, len(data) | ||
) | ||
if res != 1: | ||
self._backend._consume_errors() | ||
raise exceptions.InvalidSignature | ||
|
||
|
||
@utils.register_interface(Ed25519PrivateKey) | ||
class _Ed25519PrivateKey(object): | ||
def __init__(self, backend, evp_pkey): | ||
self._backend = backend | ||
self._evp_pkey = evp_pkey | ||
|
||
def public_key(self): | ||
bio = self._backend._create_mem_bio_gc() | ||
res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey) | ||
self._backend.openssl_assert(res == 1) | ||
evp_pkey = self._backend._lib.d2i_PUBKEY_bio( | ||
bio, self._backend._ffi.NULL | ||
) | ||
return _Ed25519PublicKey(self._backend, evp_pkey) | ||
|
||
def sign(self, data): | ||
evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() | ||
self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) | ||
evp_md_ctx = self._backend._ffi.gc( | ||
evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free | ||
) | ||
res = self._backend._lib.EVP_DigestSignInit( | ||
evp_md_ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, | ||
self._backend._ffi.NULL, self._evp_pkey | ||
) | ||
self._backend.openssl_assert(res == 1) | ||
buf = self._backend._ffi.new("unsigned char[]", 64) | ||
buflen = self._backend._ffi.new("size_t *", len(buf)) | ||
res = self._backend._lib.EVP_DigestSign( | ||
evp_md_ctx, buf, buflen, data, len(data) | ||
) | ||
self._backend.openssl_assert(res == 1) | ||
self._backend.openssl_assert(buflen[0] == 64) | ||
return self._backend._ffi.buffer(buf, buflen[0])[:] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# This file is dual licensed under the terms of the Apache License, Version | ||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository | ||
# for complete details. | ||
|
||
from __future__ import absolute_import, division, print_function | ||
|
||
import abc | ||
|
||
import six | ||
|
||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons | ||
|
||
|
||
@six.add_metaclass(abc.ABCMeta) | ||
class Ed25519PublicKey(object): | ||
@classmethod | ||
def from_public_bytes(cls, data): | ||
from cryptography.hazmat.backends.openssl.backend import backend | ||
if not backend.ed25519_supported(): | ||
raise UnsupportedAlgorithm( | ||
"ed25519 is not supported by this version of OpenSSL.", | ||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM | ||
) | ||
return backend.ed25519_load_public_bytes(data) | ||
|
||
@abc.abstractmethod | ||
def public_bytes(self): | ||
pass | ||
|
||
@abc.abstractmethod | ||
def verify(self, signature, data): | ||
pass | ||
|
||
|
||
@six.add_metaclass(abc.ABCMeta) | ||
class Ed25519PrivateKey(object): | ||
@classmethod | ||
def generate(cls): | ||
from cryptography.hazmat.backends.openssl.backend import backend | ||
if not backend.ed25519_supported(): | ||
raise UnsupportedAlgorithm( | ||
"ed25519 is not supported by this version of OpenSSL.", | ||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM | ||
) | ||
return backend.ed25519_generate_key() | ||
|
||
@classmethod | ||
def from_private_bytes(cls, data): | ||
from cryptography.hazmat.backends.openssl.backend import backend | ||
return backend.ed25519_load_private_bytes(data) | ||
|
||
@abc.abstractmethod | ||
def public_key(self): | ||
pass | ||
|
||
@abc.abstractmethod | ||
def sign(self, data): | ||
pass |
Oops, something went wrong.