Skip to content

Commit

Permalink
X509 certificate support (#110)
Browse files Browse the repository at this point in the history
libbbcsig library supports public key certificate in X509, with some refactoring in libbbcsig.c and bbclib.py. For MacOS, the filename extension of the library file is modified to "libbbcsig.dylib".
* implement X509 read function
* implement read_x509() in libbbcsig and import_publickey_cert_pem() in bbclib.py
  • Loading branch information
quvox committed Oct 8, 2018
1 parent e5dcecd commit 5b3cf90
Show file tree
Hide file tree
Showing 9 changed files with 904 additions and 456 deletions.
48 changes: 37 additions & 11 deletions bbc1/core/bbclib.py
Expand Up @@ -16,6 +16,7 @@
"""
import sys
import os
import platform
import binascii
import hashlib
import msgpack
Expand All @@ -34,10 +35,12 @@
directory, filename = os.path.split(os.path.realpath(__file__))
from ctypes import *

if os.name == "nt":
libbbcsig = CDLL("%s/libbbcsig.dll" % directory)
if platform.system() == "Windows":
libbbcsig = windll.LoadLibrary(os.path.join(directory, "libbbcsig.dll"))
elif platform.system() == "Darwin":
libbbcsig = cdll.LoadLibrary(os.path.join(directory, "libbbcsig.dylib"))
else:
libbbcsig = CDLL("%s/libbbcsig.so" % directory)
libbbcsig = cdll.LoadLibrary(os.path.join(directory, "libbbcsig.so"))


domain_global_0 = binascii.a2b_hex("0000000000000000000000000000000000000000000000000000000000000000")
Expand Down Expand Up @@ -382,25 +385,30 @@ class KeyType:


class KeyPair:
POINT_CONVERSION_COMPRESSED = 2 # same as enum point_conversion_form_t in openssl/crypto/ec.h
POINT_CONVERSION_UNCOMPRESSED = 4 # same as enum point_conversion_form_t in openssl/crypto/ec.h

"""Key pair container"""
def __init__(self, curvetype=DEFAULT_CURVETYPE, privkey=None, pubkey=None):
def __init__(self, curvetype=DEFAULT_CURVETYPE, compression=False, privkey=None, pubkey=None):
self.curvetype = curvetype
self.private_key_len = c_int32(32)
self.private_key = (c_byte * self.private_key_len.value)()
self.public_key_len = c_int32(65)
if compression:
self.public_key_len = c_int32(33)
self.key_compression = KeyPair.POINT_CONVERSION_COMPRESSED
else:
self.public_key_len = c_int32(65)
self.key_compression = KeyPair.POINT_CONVERSION_UNCOMPRESSED
self.public_key = (c_byte * self.public_key_len.value)()
if privkey is not None:
memmove(self.private_key, bytes(privkey), sizeof(self.private_key))
if pubkey is not None:
self.public_key_len = c_int32(len(pubkey))
memmove(self.public_key, bytes(pubkey), self.public_key_len.value)

if privkey is None and pubkey is None:
self.generate()

def generate(self):
"""Generate a new key pair"""
libbbcsig.generate_keypair(self.curvetype, 0, byref(self.public_key_len), self.public_key,
libbbcsig.generate_keypair(self.curvetype, self.key_compression, byref(self.public_key_len), self.public_key,
byref(self.private_key_len), self.private_key)

def mk_keyobj_from_private_key(self):
Expand All @@ -415,16 +423,34 @@ def mk_keyobj_from_private_key_der(self, derdat):
der_len = len(derdat)
der_data = (c_byte * der_len)()
memmove(der_data, bytes(derdat), der_len)
libbbcsig.convert_from_der(self.curvetype, der_len, byref(der_data), 0,
libbbcsig.convert_from_der(der_len, byref(der_data), self.key_compression,
byref(self.public_key_len), self.public_key,
byref(self.private_key_len), self.private_key)

def mk_keyobj_from_private_key_pem(self, pemdat_string):
"""Make a keypair object from the private key in PEM format"""
libbbcsig.convert_from_pem(self.curvetype, create_string_buffer(pemdat_string.encode()), 0,
libbbcsig.convert_from_pem(create_string_buffer(pemdat_string.encode()), self.key_compression,
byref(self.public_key_len), self.public_key,
byref(self.private_key_len), self.private_key)

def import_publickey_cert_pem(self, cert_pemstring, privkey_pemstring=None):
"""Verify and import X509 public key certificate in pem format"""
if privkey_pemstring is not None:
ret = libbbcsig.verify_x509(create_string_buffer(cert_pemstring.encode()),
create_string_buffer(privkey_pemstring.encode()))
else:
ret = libbbcsig.verify_x509(create_string_buffer(cert_pemstring.encode()), None)
if ret != 1:
return False

if privkey_pemstring is not None:
self.mk_keyobj_from_private_key_pem(privkey_pemstring)
else:
ret = libbbcsig.read_x509(create_string_buffer(cert_pemstring.encode()), self.key_compression, byref(self.public_key_len), self.public_key)
if ret != 1:
return False
return True

def to_binary(self, dat):
byteval = bytearray()
if self.public_key_len > 0:
Expand Down
13 changes: 9 additions & 4 deletions libs/libbbcsig/Makefile
Expand Up @@ -7,27 +7,32 @@ UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
LFLAGS0 =
LFLAGS1 =
LFLAGS2 =
LFLAGS2 =
TARGET = libbbcsig.dylib
else
LFLAGS0 = -fPIC
LFLAGS1 = -Wl,--whole-archive
LFLAGS2 = -Wl,--no-whole-archive
TARGET = libbbcsig.so
endif

.c.o:
$(CC) $(INCS) $(LFLAGS0) -c $<

all:
make libbbcsig.so
make $(TARGET)

libbbcsig.so: libbbcsig.o
gcc -shared -o $@ $(LFLAGS1) $(LIBS) $(LFLAGS2) $<
install -m 0644 $@ ../
install -m 0644 $@ ../../bbc1/core/

libbbcsig.dylib: libbbcsig.o
gcc -shared -o $@ $(LFLAGS1) $(LIBS) $(LFLAGS2) $<
install -m 0644 $@ ../../bbc1/core/

openssl:
cd $(OPENSSL_DIR) && ./config && make

clean:
rm -f libbbcsig.so libbbcsig.o
rm -f libbbcsig.so libbbcsig.dylib libbbcsig.o

10 changes: 10 additions & 0 deletions libs/libbbcsig/create-test-keys.sh
@@ -0,0 +1,10 @@
openssl ecparam -out private.key -name prime256v1 -genkey
openssl req -config openssl.cnf \
-new \
-x509 \
-key private.key \
-sha256 \
-days 1 \
-subj "/C=JP/ST=Tokyo/O=Beyond-Blockchain/CN=bbc1" \
-extensions v3_ca \
-out self-signed.pem

0 comments on commit 5b3cf90

Please sign in to comment.