Compare commits

...

7 Commits

6 changed files with 114 additions and 26 deletions
Split View
  1. +11
    -6
      README.md
  2. +37
    -0
      python/README.md
  3. +46
    -12
      python/edgold/ed448.py
  4. +17
    -3
      python/setup.py
  5. +1
    -1
      src/CMakeLists.txt
  6. +2
    -4
      src/per_curve/eddsa.tmpl.h

+ 11
- 6
README.md View File

@@ -97,10 +97,11 @@ See https://www.ristretto.group for details, once that site is up.

## Build and Install

cmake -DCMAKE_INSTALL_PREFIX=<Install path> <path to root directory>
make
make test
make install
```
cmake -DCMAKE_INSTALL_PREFIX=<Install path> <path to root directory>
make
make install
```

Most C source code is generated through a python script during the build.
Some files holding tables are generated in one more step building an
@@ -108,12 +109,16 @@ executable to generate them. They are thus stored in the source tree to help
cross-compilation. The build script update them when their dependencies
are modified, to build only these files:

make decaf_tables
```
make decaf_tables
```

Doxygen generated documentation is located in ./doc directory in the
binary tree after running

make doc
```
make doc
```

## Licensing



+ 37
- 0
python/README.md View File

@@ -0,0 +1,37 @@
Installation
------------

The easiest way to install is to run the command:
```
pip install 'git+https://git.code.sf.net/p/ed448goldilocks/code#egg=edgold&subdirectory=python'
```

After installation, the tests can be run:
```
python -m unittest edgold.ed448
```

This helps ensure that the correct architecture was detected when
compiling, and that the code works. It include a couple test vectors
from the RFC, along with verifying that the code can properly interact
with the library.

Usage
-----

This wraps the Ed448 code into a simple to use class, EDDSA448. The
easiest way to geenrate a new key is to use the generate class method.

Example:
```
from edgold.ed448 import EDDSA448

key = EDDSA448.generate()
privkey = key.export(key('raw')
msg = b'This is a message to sign'
sig = key.sign(msg)

pubkey = key.public_key().export_key('raw')
key = EDDSA448(pub=pubkey)
key.verify(sig, msg)
```

+ 46
- 12
python/edgold/ed448.py View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright 2017 John-Mark Gurney.
# Copyright 2017, 2022 John-Mark Gurney.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,10 +33,11 @@ of signing due to the complexity of integration w/ the library, and
that things should be more simple to use.'''

__author__ = 'John-Mark Gurney'
__copyright__ = 'Copyright 2017 John-Mark Gurney'''
__license__ = 'BSD'
__version__ = '0.1'
__status__ = 'alpha'
__copyright__ = 'Copyright 2017, 2022 John-Mark Gurney'''
__license__ = 'BSD-2-Clause'
__version__ = '1.0'

__all__ = [ 'EDDSA448', 'generate' ]

import array
import os
@@ -94,13 +95,7 @@ def _makeba(s):
return r

def _makestr(a):
# XXX - because python3 sucks, and unittest doesn't offer
# ability to silence stupid warnings, hide the tostring
# DeprecationWarning.
with warnings.catch_warnings():
warnings.simplefilter('ignore')
return array.array('B', a).tostring()

return bytes(a)

def _ed448_privkey():
return _makeba(os.urandom(DECAF_EDDSA_448_PRIVATE_BYTES))
@@ -286,7 +281,46 @@ class TestEd448(unittest.TestCase):
# Make sure it fails w/ invalid/different context
self.assertRaises(ValueError, key.verify, sig, message, ctx + b'a')

# https://www.rfc-editor.org/rfc/rfc8032#section-7.4
# secret key, public key, message, context, signature
_rfc8032testvectors = [
('6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b',
'5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180',
'',
'',
'533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600'),
('c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e',
'43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480',
'03',
'666f6f',
'd4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00'),
]

class TestBasicLib(unittest.TestCase):
def test_kat(self):
for idx, (key, pubkey, msg, ctx, checksig) in \
enumerate(map(bytes.fromhex, x) for x in
_rfc8032testvectors):
with self.subTest(idx=idx):
priv = _makeba(key)
pub = ed448_pubkey_t()

decaf.decaf_ed448_derive_public_key(pub, priv)

self.assertEqual(pubkey, _makestr(pub))

sig = ed448_sig_t()
if not ctx:
ctx = None
ctxargs = EDDSA448._makectxargs(ctx)

decaf.decaf_ed448_sign(sig, priv, pub, _makeba(msg), len(msg), 0, *ctxargs)

self.assertEqual(checksig, _makestr(sig))

r = decaf.decaf_ed448_verify(sig, pub, _makeba(msg), len(msg), 0, *ctxargs)
self.assertTrue(r)

def test_basic(self):
priv = _ed448_privkey()
pub = ed448_pubkey_t()


+ 17
- 3
python/setup.py View File

@@ -4,19 +4,33 @@ from distutils.command.build import build
from distutils.core import setup

import os
import sys

def libname(ver):
vars = dict(
name='libdecaf',
ver=ver,
)

if sys.platform == 'darwin':
return '%(name)s.%(ver)d.dylib' % vars

return '%(name)s.so.%(ver)d' % vars

class my_build(build):
def run(self):
build.run(self)
if not self.dry_run:
os.spawnlp(os.P_WAIT, 'sh', 'sh', '-c', 'cd .. && gmake lib')
self.copy_file(os.path.join('..', 'build', 'lib', 'libdecaf.so'), os.path.join(self.build_lib, 'edgold'))
os.spawnlp(os.P_WAIT, 'sh', 'sh', '-c',
'cd .. && mkdir build && cd build && cmake .. && make')
self.copy_file(os.path.join('..', 'build', 'src', libname(0)),
os.path.join(self.build_lib, 'edgold', 'libdecaf.so'))

cmdclass = {}
cmdclass['build'] = my_build

setup(name='edgold',
version='0.1',
version='1.0',
description='The Ed ECC Goldilocks Python wrapper',
author='John-Mark Gurney',
author_email='jmg@funkthat.com',


+ 1
- 1
src/CMakeLists.txt View File

@@ -42,7 +42,7 @@ if(MSVC)# On MSVC Windows, Processor is always AMD64 on both platforms (x86/x64)
else()
set(MSVC_ARCH ${CMAKE_SYSTEM_PROCESSOR})# just to have a value
endif()
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" AND NOT MSVC)#Decaf doesn't support 64bits on MSVC yet
if((${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "amd64") AND NOT MSVC)#Decaf doesn't support 64bits on MSVC yet
message("Target architecture is x86_64")
set(TARGET_ARCH_DIR arch_x86_64)
set(TARGET_ARCH_DIR_P25519 arch_x86_64)


+ 2
- 4
src/per_curve/eddsa.tmpl.h View File

@@ -143,8 +143,7 @@ void DECAF_API_VIS decaf_ed$(gf_shortname)_sign (
uint8_t context_len
) __attribute__((nonnull(1,2,3))) DECAF_NOINLINE
#if DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED
__attribute__((deprecated("Passing the pubkey and privkey separately is unsafe",
"decaf_ed$(gf_shortname)_keypair_sign")))
__attribute__((deprecated("Passing the pubkey and privkey separately is unsafe decaf_ed$(gf_shortname)_keypair_sign")))
#endif
;

@@ -171,8 +170,7 @@ void DECAF_API_VIS decaf_ed$(gf_shortname)_sign_prehash (
uint8_t context_len
) __attribute__((nonnull(1,2,3,4))) DECAF_NOINLINE
#if DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED
__attribute__((deprecated("Passing the pubkey and privkey separately is unsafe",
"decaf_ed$(gf_shortname)_keypair_sign_prehash")))
__attribute__((deprecated("Passing the pubkey and privkey separately is unsafe decaf_ed$(gf_shortname)_keypair_sign_prehash")))
#endif
;



Loading…
Cancel
Save