eddsa 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eddsa-0.8.0/CMakeLists.txt +65 -0
- eddsa-0.8.0/LICENSE +25 -0
- eddsa-0.8.0/MANIFEST.in +11 -0
- eddsa-0.8.0/PKG-INFO +59 -0
- eddsa-0.8.0/README.md +32 -0
- eddsa-0.8.0/build_tools/CheckVersion.py +28 -0
- eddsa-0.8.0/build_tools/RunCTest.py +51 -0
- eddsa-0.8.0/build_tools/__init__.py +1 -0
- eddsa-0.8.0/eddsa/__init__.py +37 -0
- eddsa-0.8.0/eddsa/_eddsa.c +251 -0
- eddsa-0.8.0/eddsa/_eddsa.exports +1 -0
- eddsa-0.8.0/eddsa/_eddsa.map +6 -0
- eddsa-0.8.0/eddsa/_vendor/lib/bitness.h +12 -0
- eddsa-0.8.0/eddsa/_vendor/lib/burn.c +14 -0
- eddsa-0.8.0/eddsa/_vendor/lib/burn.h +26 -0
- eddsa-0.8.0/eddsa/_vendor/lib/burnstack.c +21 -0
- eddsa-0.8.0/eddsa/_vendor/lib/burnstack.h +16 -0
- eddsa-0.8.0/eddsa/_vendor/lib/compat.h +14 -0
- eddsa-0.8.0/eddsa/_vendor/lib/ed.c +507 -0
- eddsa-0.8.0/eddsa/_vendor/lib/ed.h +29 -0
- eddsa-0.8.0/eddsa/_vendor/lib/ed25519-sha512.c +324 -0
- eddsa-0.8.0/eddsa/_vendor/lib/ed_lookup32.h +1603 -0
- eddsa-0.8.0/eddsa/_vendor/lib/ed_lookup64.h +835 -0
- eddsa-0.8.0/eddsa/_vendor/lib/eddsa.h +122 -0
- eddsa-0.8.0/eddsa/_vendor/lib/fld.c +709 -0
- eddsa-0.8.0/eddsa/_vendor/lib/fld.h +144 -0
- eddsa-0.8.0/eddsa/_vendor/lib/limb.h +21 -0
- eddsa-0.8.0/eddsa/_vendor/lib/sc.c +324 -0
- eddsa-0.8.0/eddsa/_vendor/lib/sc.h +64 -0
- eddsa-0.8.0/eddsa/_vendor/lib/sha512.c +210 -0
- eddsa-0.8.0/eddsa/_vendor/lib/sha512.h +31 -0
- eddsa-0.8.0/eddsa/_vendor/lib/x25519.c +243 -0
- eddsa-0.8.0/eddsa.egg-info/PKG-INFO +59 -0
- eddsa-0.8.0/eddsa.egg-info/SOURCES.txt +29 -0
- eddsa-0.8.0/eddsa.egg-info/dependency_links.txt +1 -0
- eddsa-0.8.0/eddsa.egg-info/top_level.txt +1 -0
- eddsa-0.8.0/pyproject.toml +3 -0
- eddsa-0.8.0/setup.cfg +4 -0
- eddsa-0.8.0/setup.py +203 -0
- eddsa-0.8.0/tests/test_eddsa.py +64 -0
- eddsa-0.8.0/tests/test_symbols.py +32 -0
- eddsa-0.8.0/tools/benchmark.py +122 -0
- eddsa-0.8.0/tools/benchmark_c.py +162 -0
- eddsa-0.8.0/tools/benchmark_summary.py +252 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
include(CheckCCompilerFlag)
|
|
2
|
+
include(CheckPrototypeDefinition)
|
|
3
|
+
|
|
4
|
+
cmake_minimum_required(VERSION 3.0.0)
|
|
5
|
+
|
|
6
|
+
project(eddsa C)
|
|
7
|
+
|
|
8
|
+
set(EDDSA_VERSION_MAJOR 0)
|
|
9
|
+
set(EDDSA_VERSION_MINOR 8)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
option(USE_STACKCLEAN "clean all secret variables from stack" ON)
|
|
13
|
+
option(BUILD_STATIC "build static version of library" ON)
|
|
14
|
+
option(BUILD_TESTING "build test" ON)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if (UNIX)
|
|
18
|
+
set(CMAKE_C_FLAGS "-std=c99 -fwrapv -Wall -Wextra -pedantic -O3")
|
|
19
|
+
endif ()
|
|
20
|
+
|
|
21
|
+
# check for memset_s and co
|
|
22
|
+
#
|
|
23
|
+
check_prototype_definition(memset_s
|
|
24
|
+
"errno_t memset_s( void *dest, rsize_t destsz, int ch, rsize_t count )"
|
|
25
|
+
"0"
|
|
26
|
+
"string.h"
|
|
27
|
+
HAVE_MEMSET_S)
|
|
28
|
+
|
|
29
|
+
check_prototype_definition(explicit_bzero
|
|
30
|
+
"void explicit_bzero(void *b, size_t len)"
|
|
31
|
+
""
|
|
32
|
+
"string.h"
|
|
33
|
+
HAVE_EXPLICIT_BZERO)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# does our compiler have hidden-visibility feature?
|
|
37
|
+
#
|
|
38
|
+
if (NOT (CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2")
|
|
39
|
+
AND NOT WIN32
|
|
40
|
+
AND NOT CYGWIN)
|
|
41
|
+
check_c_compiler_flag("-fvisibility=hidden" HAVE_VISIBILITY)
|
|
42
|
+
endif ()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# add library source code
|
|
47
|
+
#
|
|
48
|
+
add_subdirectory(lib)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# add test source if requested
|
|
52
|
+
#
|
|
53
|
+
if (BUILD_TESTING)
|
|
54
|
+
enable_testing()
|
|
55
|
+
add_subdirectory(test)
|
|
56
|
+
endif ()
|
|
57
|
+
|
|
58
|
+
if (NOT BITNESS)
|
|
59
|
+
set(BITNESS autodetect)
|
|
60
|
+
endif ()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
MESSAGE("bitness: " ${BITNESS})
|
|
64
|
+
MESSAGE("cleanup stack: " ${USE_STACKCLEAN})
|
|
65
|
+
MESSAGE("build test: " ${BUILD_TESTING})
|
eddsa-0.8.0/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <http://unlicense.org>
|
|
25
|
+
|
eddsa-0.8.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
include pyproject.toml
|
|
2
|
+
include setup.py
|
|
3
|
+
include MANIFEST.in
|
|
4
|
+
include CMakeLists.txt
|
|
5
|
+
recursive-include build_tools *.py
|
|
6
|
+
include eddsa/__init__.py
|
|
7
|
+
include eddsa/_eddsa.c
|
|
8
|
+
include eddsa/_eddsa.map
|
|
9
|
+
include eddsa/_eddsa.exports
|
|
10
|
+
recursive-include tools *.py
|
|
11
|
+
recursive-include tests *.py
|
eddsa-0.8.0/PKG-INFO
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eddsa
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: CPython wrapper for libeddsa Ed25519 and X25519 primitives
|
|
5
|
+
Home-page: https://github.com/sippy/py-eddsa.git
|
|
6
|
+
Author: Maksym Sobolyev
|
|
7
|
+
Author-email: sobomax@gmail.com
|
|
8
|
+
License: Unlicense
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Operating System :: MacOS
|
|
11
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
12
|
+
Classifier: Operating System :: POSIX
|
|
13
|
+
Classifier: Programming Language :: C
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Security :: Cryptography
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: author-email
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: license
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# libeddsa
|
|
29
|
+
|
|
30
|
+
This is a small cryptographic library for signatures with [ed25519](http://ed25519.cr.yp.to/ed25519-20110705.pdf) and diffie-hellman key exchange with [x25519](http://cr.yp.to/ecdh/curve25519-20060209.pdf).
|
|
31
|
+
|
|
32
|
+
My goal is to give a fast, but still readable, C implemantation of these two crypto primitives without any complex framework. (If you need a full and easy to use framework with symmetric cipher and MAC included, please have a look at [libnacl](http://nacl.cr.yp.to) or [libsodium](https://github.com/jedisct1/libsodium) which are both great.)
|
|
33
|
+
|
|
34
|
+
If you need just ed25519-signatures or x25519-key-exchange with a simple API, however, libeddsa may be for you: It is small (under 90kb) and quite fast.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Features:
|
|
38
|
+
- written in C
|
|
39
|
+
- fast and small
|
|
40
|
+
- cmake build system
|
|
41
|
+
- protection against timing attacks as far as possible in C
|
|
42
|
+
- static and dynamic link support
|
|
43
|
+
- easy to use (see wiki)
|
|
44
|
+
- public domain license
|
|
45
|
+
|
|
46
|
+
### Python bindings
|
|
47
|
+
|
|
48
|
+
The CPython module is packaged from `python/` and exposes the public libeddsa
|
|
49
|
+
API as byte-oriented functions:
|
|
50
|
+
|
|
51
|
+
- `ed25519_genpub(sec) -> bytes`
|
|
52
|
+
- `ed25519_sign(sec, pub, data) -> bytes`
|
|
53
|
+
- `ed25519_verify(sig, pub, data) -> bool`
|
|
54
|
+
- `x25519_base(scalar) -> bytes`
|
|
55
|
+
- `x25519(scalar, point) -> bytes`
|
|
56
|
+
- `pk_ed25519_to_x25519(pub) -> bytes`
|
|
57
|
+
- `sk_ed25519_to_x25519(sec) -> bytes`
|
|
58
|
+
|
|
59
|
+
The obsolete C API names are also provided as compatibility aliases.
|
eddsa-0.8.0/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# libeddsa
|
|
2
|
+
|
|
3
|
+
This is a small cryptographic library for signatures with [ed25519](http://ed25519.cr.yp.to/ed25519-20110705.pdf) and diffie-hellman key exchange with [x25519](http://cr.yp.to/ecdh/curve25519-20060209.pdf).
|
|
4
|
+
|
|
5
|
+
My goal is to give a fast, but still readable, C implemantation of these two crypto primitives without any complex framework. (If you need a full and easy to use framework with symmetric cipher and MAC included, please have a look at [libnacl](http://nacl.cr.yp.to) or [libsodium](https://github.com/jedisct1/libsodium) which are both great.)
|
|
6
|
+
|
|
7
|
+
If you need just ed25519-signatures or x25519-key-exchange with a simple API, however, libeddsa may be for you: It is small (under 90kb) and quite fast.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features:
|
|
11
|
+
- written in C
|
|
12
|
+
- fast and small
|
|
13
|
+
- cmake build system
|
|
14
|
+
- protection against timing attacks as far as possible in C
|
|
15
|
+
- static and dynamic link support
|
|
16
|
+
- easy to use (see wiki)
|
|
17
|
+
- public domain license
|
|
18
|
+
|
|
19
|
+
### Python bindings
|
|
20
|
+
|
|
21
|
+
The CPython module is packaged from `python/` and exposes the public libeddsa
|
|
22
|
+
API as byte-oriented functions:
|
|
23
|
+
|
|
24
|
+
- `ed25519_genpub(sec) -> bytes`
|
|
25
|
+
- `ed25519_sign(sec, pub, data) -> bytes`
|
|
26
|
+
- `ed25519_verify(sig, pub, data) -> bool`
|
|
27
|
+
- `x25519_base(scalar) -> bytes`
|
|
28
|
+
- `x25519(scalar, point) -> bytes`
|
|
29
|
+
- `pk_ed25519_to_x25519(pub) -> bytes`
|
|
30
|
+
- `sk_ed25519_to_x25519(sec) -> bytes`
|
|
31
|
+
|
|
32
|
+
The obsolete C API names are also provided as compatibility aliases.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from distutils.errors import DistutilsOptionError
|
|
3
|
+
|
|
4
|
+
from setuptools import Command
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CheckVersion(Command):
|
|
8
|
+
description = "Check package version against a git tag"
|
|
9
|
+
user_options = [
|
|
10
|
+
("tag=", "t", "git tag to compare against package version"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
def initialize_options(self):
|
|
14
|
+
self.tag = None
|
|
15
|
+
|
|
16
|
+
def finalize_options(self):
|
|
17
|
+
if not self.tag:
|
|
18
|
+
raise DistutilsOptionError("You must specify --tag")
|
|
19
|
+
|
|
20
|
+
def run(self):
|
|
21
|
+
pkg_version = self.distribution.get_version()
|
|
22
|
+
accepted_tags = {f"v{pkg_version}"}
|
|
23
|
+
if pkg_version.endswith(".0"):
|
|
24
|
+
accepted_tags.add(f"v{pkg_version[:-2]}")
|
|
25
|
+
if self.tag in accepted_tags:
|
|
26
|
+
return
|
|
27
|
+
sys.stderr.write(f"version {pkg_version} does not match tag {self.tag}\n")
|
|
28
|
+
sys.exit(1)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from setuptools import Command
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RunCTest(Command):
|
|
10
|
+
description = "Build and run the C self-tests"
|
|
11
|
+
user_options = []
|
|
12
|
+
root_dir = Path(__file__).resolve().parents[2]
|
|
13
|
+
|
|
14
|
+
def initialize_options(self):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def finalize_options(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
def run(self):
|
|
21
|
+
build_dir = self.root_dir / "build" / "python-ctest"
|
|
22
|
+
if build_dir.exists():
|
|
23
|
+
shutil.rmtree(build_dir)
|
|
24
|
+
build_dir.mkdir(parents=True)
|
|
25
|
+
|
|
26
|
+
env = os.environ.copy()
|
|
27
|
+
subprocess.run(
|
|
28
|
+
[
|
|
29
|
+
"cmake",
|
|
30
|
+
"-S",
|
|
31
|
+
str(self.root_dir),
|
|
32
|
+
"-B",
|
|
33
|
+
str(build_dir),
|
|
34
|
+
"-DBUILD_STATIC=ON",
|
|
35
|
+
"-DBUILD_TESTING=ON",
|
|
36
|
+
"-DCMAKE_BUILD_TYPE=Release",
|
|
37
|
+
"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
|
|
38
|
+
],
|
|
39
|
+
check=True,
|
|
40
|
+
env=env,
|
|
41
|
+
)
|
|
42
|
+
subprocess.run(
|
|
43
|
+
["cmake", "--build", str(build_dir), "--config", "Release"],
|
|
44
|
+
check=True,
|
|
45
|
+
env=env,
|
|
46
|
+
)
|
|
47
|
+
subprocess.run(
|
|
48
|
+
["ctest", "--test-dir", str(build_dir), "--output-on-failure", "-C", "Release"],
|
|
49
|
+
check=True,
|
|
50
|
+
env=env,
|
|
51
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from ._eddsa import (
|
|
2
|
+
DH,
|
|
3
|
+
ED25519_KEY_LEN,
|
|
4
|
+
ED25519_SIG_LEN,
|
|
5
|
+
X25519_KEY_LEN,
|
|
6
|
+
ed25519_genpub,
|
|
7
|
+
ed25519_sign,
|
|
8
|
+
ed25519_verify,
|
|
9
|
+
eddsa_genpub,
|
|
10
|
+
eddsa_pk_eddsa_to_dh,
|
|
11
|
+
eddsa_sign,
|
|
12
|
+
eddsa_sk_eddsa_to_dh,
|
|
13
|
+
eddsa_verify,
|
|
14
|
+
pk_ed25519_to_x25519,
|
|
15
|
+
sk_ed25519_to_x25519,
|
|
16
|
+
x25519,
|
|
17
|
+
x25519_base,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"ED25519_KEY_LEN",
|
|
22
|
+
"ED25519_SIG_LEN",
|
|
23
|
+
"X25519_KEY_LEN",
|
|
24
|
+
"ed25519_genpub",
|
|
25
|
+
"ed25519_sign",
|
|
26
|
+
"ed25519_verify",
|
|
27
|
+
"x25519_base",
|
|
28
|
+
"x25519",
|
|
29
|
+
"pk_ed25519_to_x25519",
|
|
30
|
+
"sk_ed25519_to_x25519",
|
|
31
|
+
"eddsa_genpub",
|
|
32
|
+
"eddsa_sign",
|
|
33
|
+
"eddsa_verify",
|
|
34
|
+
"DH",
|
|
35
|
+
"eddsa_pk_eddsa_to_dh",
|
|
36
|
+
"eddsa_sk_eddsa_to_dh",
|
|
37
|
+
]
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#define PY_SSIZE_T_CLEAN
|
|
2
|
+
#include <Python.h>
|
|
3
|
+
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
|
|
6
|
+
#include "eddsa.h"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
10
|
+
#define PYEDDSA_MODINIT_FUNC __declspec(dllexport) PyObject *
|
|
11
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
|
12
|
+
#define PYEDDSA_MODINIT_FUNC __attribute__((visibility("default"))) PyObject *
|
|
13
|
+
#else
|
|
14
|
+
#define PYEDDSA_MODINIT_FUNC PyObject *
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
static int
|
|
19
|
+
expect_len(const Py_buffer *buffer, Py_ssize_t expected, const char *name)
|
|
20
|
+
{
|
|
21
|
+
if (buffer->len == expected) {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
PyErr_Format(PyExc_ValueError, "%s must be exactly %zd bytes", name, expected);
|
|
25
|
+
return -1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static PyObject *
|
|
29
|
+
py_ed25519_genpub(PyObject *self, PyObject *args)
|
|
30
|
+
{
|
|
31
|
+
Py_buffer sec;
|
|
32
|
+
PyObject *result;
|
|
33
|
+
|
|
34
|
+
(void)self;
|
|
35
|
+
if (!PyArg_ParseTuple(args, "y*:ed25519_genpub", &sec)) {
|
|
36
|
+
return NULL;
|
|
37
|
+
}
|
|
38
|
+
if (expect_len(&sec, ED25519_KEY_LEN, "sec") < 0) {
|
|
39
|
+
PyBuffer_Release(&sec);
|
|
40
|
+
return NULL;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
result = PyBytes_FromStringAndSize(NULL, ED25519_KEY_LEN);
|
|
44
|
+
if (result != NULL) {
|
|
45
|
+
ed25519_genpub((uint8_t *)PyBytes_AS_STRING(result), (const uint8_t *)sec.buf);
|
|
46
|
+
}
|
|
47
|
+
PyBuffer_Release(&sec);
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static PyObject *
|
|
52
|
+
py_ed25519_sign(PyObject *self, PyObject *args)
|
|
53
|
+
{
|
|
54
|
+
Py_buffer sec;
|
|
55
|
+
Py_buffer pub;
|
|
56
|
+
Py_buffer data;
|
|
57
|
+
PyObject *result;
|
|
58
|
+
|
|
59
|
+
(void)self;
|
|
60
|
+
if (!PyArg_ParseTuple(args, "y*y*y*:ed25519_sign", &sec, &pub, &data)) {
|
|
61
|
+
return NULL;
|
|
62
|
+
}
|
|
63
|
+
if (expect_len(&sec, ED25519_KEY_LEN, "sec") < 0 ||
|
|
64
|
+
expect_len(&pub, ED25519_KEY_LEN, "pub") < 0) {
|
|
65
|
+
PyBuffer_Release(&data);
|
|
66
|
+
PyBuffer_Release(&pub);
|
|
67
|
+
PyBuffer_Release(&sec);
|
|
68
|
+
return NULL;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
result = PyBytes_FromStringAndSize(NULL, ED25519_SIG_LEN);
|
|
72
|
+
if (result != NULL) {
|
|
73
|
+
ed25519_sign((uint8_t *)PyBytes_AS_STRING(result),
|
|
74
|
+
(const uint8_t *)sec.buf, (const uint8_t *)pub.buf,
|
|
75
|
+
(const uint8_t *)data.buf, (size_t)data.len);
|
|
76
|
+
}
|
|
77
|
+
PyBuffer_Release(&data);
|
|
78
|
+
PyBuffer_Release(&pub);
|
|
79
|
+
PyBuffer_Release(&sec);
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static PyObject *
|
|
84
|
+
py_ed25519_verify(PyObject *self, PyObject *args)
|
|
85
|
+
{
|
|
86
|
+
Py_buffer sig;
|
|
87
|
+
Py_buffer pub;
|
|
88
|
+
Py_buffer data;
|
|
89
|
+
bool ok;
|
|
90
|
+
|
|
91
|
+
(void)self;
|
|
92
|
+
if (!PyArg_ParseTuple(args, "y*y*y*:ed25519_verify", &sig, &pub, &data)) {
|
|
93
|
+
return NULL;
|
|
94
|
+
}
|
|
95
|
+
if (expect_len(&sig, ED25519_SIG_LEN, "sig") < 0 ||
|
|
96
|
+
expect_len(&pub, ED25519_KEY_LEN, "pub") < 0) {
|
|
97
|
+
PyBuffer_Release(&data);
|
|
98
|
+
PyBuffer_Release(&pub);
|
|
99
|
+
PyBuffer_Release(&sig);
|
|
100
|
+
return NULL;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
ok = ed25519_verify((const uint8_t *)sig.buf, (const uint8_t *)pub.buf,
|
|
104
|
+
(const uint8_t *)data.buf, (size_t)data.len);
|
|
105
|
+
PyBuffer_Release(&data);
|
|
106
|
+
PyBuffer_Release(&pub);
|
|
107
|
+
PyBuffer_Release(&sig);
|
|
108
|
+
return PyBool_FromLong(ok);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static PyObject *
|
|
112
|
+
py_x25519_base(PyObject *self, PyObject *args)
|
|
113
|
+
{
|
|
114
|
+
Py_buffer scalar;
|
|
115
|
+
PyObject *result;
|
|
116
|
+
|
|
117
|
+
(void)self;
|
|
118
|
+
if (!PyArg_ParseTuple(args, "y*:x25519_base", &scalar)) {
|
|
119
|
+
return NULL;
|
|
120
|
+
}
|
|
121
|
+
if (expect_len(&scalar, X25519_KEY_LEN, "scalar") < 0) {
|
|
122
|
+
PyBuffer_Release(&scalar);
|
|
123
|
+
return NULL;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
result = PyBytes_FromStringAndSize(NULL, X25519_KEY_LEN);
|
|
127
|
+
if (result != NULL) {
|
|
128
|
+
x25519_base((uint8_t *)PyBytes_AS_STRING(result), (const uint8_t *)scalar.buf);
|
|
129
|
+
}
|
|
130
|
+
PyBuffer_Release(&scalar);
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static PyObject *
|
|
135
|
+
py_x25519(PyObject *self, PyObject *args)
|
|
136
|
+
{
|
|
137
|
+
Py_buffer scalar;
|
|
138
|
+
Py_buffer point;
|
|
139
|
+
PyObject *result;
|
|
140
|
+
|
|
141
|
+
(void)self;
|
|
142
|
+
if (!PyArg_ParseTuple(args, "y*y*:x25519", &scalar, &point)) {
|
|
143
|
+
return NULL;
|
|
144
|
+
}
|
|
145
|
+
if (expect_len(&scalar, X25519_KEY_LEN, "scalar") < 0 ||
|
|
146
|
+
expect_len(&point, X25519_KEY_LEN, "point") < 0) {
|
|
147
|
+
PyBuffer_Release(&point);
|
|
148
|
+
PyBuffer_Release(&scalar);
|
|
149
|
+
return NULL;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
result = PyBytes_FromStringAndSize(NULL, X25519_KEY_LEN);
|
|
153
|
+
if (result != NULL) {
|
|
154
|
+
x25519((uint8_t *)PyBytes_AS_STRING(result), (const uint8_t *)scalar.buf,
|
|
155
|
+
(const uint8_t *)point.buf);
|
|
156
|
+
}
|
|
157
|
+
PyBuffer_Release(&point);
|
|
158
|
+
PyBuffer_Release(&scalar);
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static PyObject *
|
|
163
|
+
py_pk_ed25519_to_x25519(PyObject *self, PyObject *args)
|
|
164
|
+
{
|
|
165
|
+
Py_buffer in;
|
|
166
|
+
PyObject *result;
|
|
167
|
+
|
|
168
|
+
(void)self;
|
|
169
|
+
if (!PyArg_ParseTuple(args, "y*:pk_ed25519_to_x25519", &in)) {
|
|
170
|
+
return NULL;
|
|
171
|
+
}
|
|
172
|
+
if (expect_len(&in, ED25519_KEY_LEN, "in") < 0) {
|
|
173
|
+
PyBuffer_Release(&in);
|
|
174
|
+
return NULL;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
result = PyBytes_FromStringAndSize(NULL, X25519_KEY_LEN);
|
|
178
|
+
if (result != NULL) {
|
|
179
|
+
pk_ed25519_to_x25519((uint8_t *)PyBytes_AS_STRING(result), (const uint8_t *)in.buf);
|
|
180
|
+
}
|
|
181
|
+
PyBuffer_Release(&in);
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static PyObject *
|
|
186
|
+
py_sk_ed25519_to_x25519(PyObject *self, PyObject *args)
|
|
187
|
+
{
|
|
188
|
+
Py_buffer in;
|
|
189
|
+
PyObject *result;
|
|
190
|
+
|
|
191
|
+
(void)self;
|
|
192
|
+
if (!PyArg_ParseTuple(args, "y*:sk_ed25519_to_x25519", &in)) {
|
|
193
|
+
return NULL;
|
|
194
|
+
}
|
|
195
|
+
if (expect_len(&in, ED25519_KEY_LEN, "in") < 0) {
|
|
196
|
+
PyBuffer_Release(&in);
|
|
197
|
+
return NULL;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
result = PyBytes_FromStringAndSize(NULL, X25519_KEY_LEN);
|
|
201
|
+
if (result != NULL) {
|
|
202
|
+
sk_ed25519_to_x25519((uint8_t *)PyBytes_AS_STRING(result), (const uint8_t *)in.buf);
|
|
203
|
+
}
|
|
204
|
+
PyBuffer_Release(&in);
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static PyMethodDef module_methods[] = {
|
|
209
|
+
{"ed25519_genpub", py_ed25519_genpub, METH_VARARGS, PyDoc_STR("Return an Ed25519 public key for a 32-byte secret key.")},
|
|
210
|
+
{"ed25519_sign", py_ed25519_sign, METH_VARARGS, PyDoc_STR("Return a 64-byte Ed25519 signature for sec, pub, and data.")},
|
|
211
|
+
{"ed25519_verify", py_ed25519_verify, METH_VARARGS, PyDoc_STR("Return True if sig verifies for pub and data.")},
|
|
212
|
+
{"x25519_base", py_x25519_base, METH_VARARGS, PyDoc_STR("Return the X25519 public value for a 32-byte scalar.")},
|
|
213
|
+
{"x25519", py_x25519, METH_VARARGS, PyDoc_STR("Return the X25519 shared value for scalar and point.")},
|
|
214
|
+
{"pk_ed25519_to_x25519", py_pk_ed25519_to_x25519, METH_VARARGS, PyDoc_STR("Convert an Ed25519 public key to an X25519 public key.")},
|
|
215
|
+
{"sk_ed25519_to_x25519", py_sk_ed25519_to_x25519, METH_VARARGS, PyDoc_STR("Convert an Ed25519 secret key to an X25519 secret key.")},
|
|
216
|
+
{"eddsa_genpub", py_ed25519_genpub, METH_VARARGS, PyDoc_STR("Obsolete alias for ed25519_genpub.")},
|
|
217
|
+
{"eddsa_sign", py_ed25519_sign, METH_VARARGS, PyDoc_STR("Obsolete alias for ed25519_sign.")},
|
|
218
|
+
{"eddsa_verify", py_ed25519_verify, METH_VARARGS, PyDoc_STR("Obsolete alias for ed25519_verify.")},
|
|
219
|
+
{"DH", py_x25519, METH_VARARGS, PyDoc_STR("Obsolete alias for x25519.")},
|
|
220
|
+
{"eddsa_pk_eddsa_to_dh", py_pk_ed25519_to_x25519, METH_VARARGS, PyDoc_STR("Obsolete alias for pk_ed25519_to_x25519.")},
|
|
221
|
+
{"eddsa_sk_eddsa_to_dh", py_sk_ed25519_to_x25519, METH_VARARGS, PyDoc_STR("Obsolete alias for sk_ed25519_to_x25519.")},
|
|
222
|
+
{NULL, NULL, 0, NULL}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
static struct PyModuleDef moduledef = {
|
|
226
|
+
PyModuleDef_HEAD_INIT,
|
|
227
|
+
"_eddsa",
|
|
228
|
+
PyDoc_STR("CPython bindings for libeddsa."),
|
|
229
|
+
-1,
|
|
230
|
+
module_methods,
|
|
231
|
+
NULL,
|
|
232
|
+
NULL,
|
|
233
|
+
NULL,
|
|
234
|
+
NULL
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
PYEDDSA_MODINIT_FUNC
|
|
238
|
+
PyInit__eddsa(void)
|
|
239
|
+
{
|
|
240
|
+
PyObject *module = PyModule_Create(&moduledef);
|
|
241
|
+
if (module == NULL) {
|
|
242
|
+
return NULL;
|
|
243
|
+
}
|
|
244
|
+
if (PyModule_AddIntConstant(module, "ED25519_KEY_LEN", ED25519_KEY_LEN) < 0 ||
|
|
245
|
+
PyModule_AddIntConstant(module, "ED25519_SIG_LEN", ED25519_SIG_LEN) < 0 ||
|
|
246
|
+
PyModule_AddIntConstant(module, "X25519_KEY_LEN", X25519_KEY_LEN) < 0) {
|
|
247
|
+
Py_DECREF(module);
|
|
248
|
+
return NULL;
|
|
249
|
+
}
|
|
250
|
+
return module;
|
|
251
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
_PyInit__eddsa
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#include <stdint.h>
|
|
2
|
+
#include <stddef.h>
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* burn - simple function to zero a buffer, used to cover our tracks
|
|
6
|
+
*/
|
|
7
|
+
void
|
|
8
|
+
burn(void *dest, size_t len)
|
|
9
|
+
{
|
|
10
|
+
volatile uint8_t *p = (uint8_t *)dest;
|
|
11
|
+
const uint8_t *end = (uint8_t *)dest+len;
|
|
12
|
+
|
|
13
|
+
while (p < end) *p++ = 0;
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#ifndef BURN_H
|
|
2
|
+
#define BURN_H
|
|
3
|
+
|
|
4
|
+
#include <stddef.h>
|
|
5
|
+
|
|
6
|
+
#include "compat.h"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
#if defined(HAVE_MEMSET_S)
|
|
10
|
+
|
|
11
|
+
#include <string.h>
|
|
12
|
+
static INLINE void burn(void *dest, size_t len) { memset_s(dest, len, 0, len); }
|
|
13
|
+
|
|
14
|
+
#elif defined(HAVE_EXPLICIT_BZERO)
|
|
15
|
+
|
|
16
|
+
#include <string.h>
|
|
17
|
+
static INLINE void burn(void *dest, size_t len) { explicit_bzero(dest, len); }
|
|
18
|
+
|
|
19
|
+
#else
|
|
20
|
+
|
|
21
|
+
void burn(void *dest, size_t len);
|
|
22
|
+
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#endif
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#include <stdint.h>
|
|
2
|
+
|
|
3
|
+
#include "burn.h"
|
|
4
|
+
#include "burnstack.h"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
#ifdef USE_STACKCLEAN
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* burnstack - cleanup our stack
|
|
11
|
+
*/
|
|
12
|
+
void
|
|
13
|
+
burnstack(int len)
|
|
14
|
+
{
|
|
15
|
+
uint8_t stack[1024];
|
|
16
|
+
burn(stack, 1024);
|
|
17
|
+
if (len > 0)
|
|
18
|
+
burnstack(len-1024);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#endif
|