Adjustments for private key and peer id
This commit is contained in:
parent
4818ac8567
commit
93dc4d558f
8 changed files with 221 additions and 19 deletions
|
@ -91,6 +91,12 @@ int libp2p_crypto_encoding_x509_der_to_private_key(unsigned char* der, size_t de
|
||||||
private_key->QP = *(rsa->QP.p);
|
private_key->QP = *(rsa->QP.p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now put the public DER format in.
|
||||||
|
private_key->der = der;
|
||||||
|
private_key->der_length = der_length;
|
||||||
|
|
||||||
|
//NOTE: the public DER stuff is done in rsa.c
|
||||||
|
|
||||||
mbedtls_pk_free(&ctx);
|
mbedtls_pk_free(&ctx);
|
||||||
|
|
||||||
return retVal >= 0;
|
return retVal >= 0;
|
||||||
|
|
35
crypto/rsa.c
35
crypto/rsa.c
|
@ -21,6 +21,7 @@
|
||||||
#include "mbedtls/rsa.h"
|
#include "mbedtls/rsa.h"
|
||||||
#include "mbedtls/asn1write.h"
|
#include "mbedtls/asn1write.h"
|
||||||
#include "mbedtls/oid.h"
|
#include "mbedtls/oid.h"
|
||||||
|
#include "mbedtls/pk.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take an rsa context and turn it into a der formatted byte stream.
|
* Take an rsa context and turn it into a der formatted byte stream.
|
||||||
|
@ -193,6 +194,40 @@ exit:
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the private key DER to fill in the public key DER
|
||||||
|
* @param private_key the private key to use
|
||||||
|
* @reutrns true(1) on success
|
||||||
|
*/
|
||||||
|
int libp2p_crypto_rsa_private_key_fill_public_key(struct RsaPrivateKey* private_key) {
|
||||||
|
// first build the rsa context
|
||||||
|
mbedtls_pk_context ctx;
|
||||||
|
mbedtls_pk_init(&ctx);
|
||||||
|
mbedtls_pk_parse_key(&ctx, private_key->der, private_key->der_length, NULL, 0);
|
||||||
|
|
||||||
|
// buffer
|
||||||
|
size_t buffer_size = 1600;
|
||||||
|
unsigned char buffer[buffer_size];
|
||||||
|
memset(buffer, 0, buffer_size);
|
||||||
|
|
||||||
|
// generate public key der
|
||||||
|
int retVal = libp2p_crypto_rsa_write_public_key_der(&ctx, buffer, &buffer_size);
|
||||||
|
if (retVal == 0) {
|
||||||
|
mbedtls_pk_free(&ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate memory for the public key der
|
||||||
|
private_key->public_key_length = buffer_size;
|
||||||
|
private_key->public_key_der = malloc(sizeof(char) * buffer_size);
|
||||||
|
|
||||||
|
//copy it into the struct
|
||||||
|
memcpy(private_key->public_key_der, &buffer[1600-buffer_size], buffer_size);
|
||||||
|
mbedtls_pk_free(&ctx);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Free resources used by RsaPrivateKey
|
* Free resources used by RsaPrivateKey
|
||||||
* @param private_key the resources
|
* @param private_key the resources
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
//
|
/**
|
||||||
// x509.h
|
* Wrappers around the x509 stuff
|
||||||
// libp2p_xcode
|
*/
|
||||||
//
|
|
||||||
// Created by John Jones on 11/7/16.
|
|
||||||
// Copyright © 2016 JMJAtlanta. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __LIBP2P_CRYPTO_ENCODING_X509_H__
|
#ifndef __LIBP2P_CRYPTO_ENCODING_X509_H__
|
||||||
#define __LIBP2P_CRYPTO_ENCODING_X509_H__
|
#define __LIBP2P_CRYPTO_ENCODING_X509_H__
|
||||||
|
|
|
@ -38,6 +38,14 @@ struct RsaPrivateKey {
|
||||||
*/
|
*/
|
||||||
int libp2p_crypto_rsa_generate_keypair(struct RsaPrivateKey* private_key, unsigned long num_bits_for_keypair);
|
int libp2p_crypto_rsa_generate_keypair(struct RsaPrivateKey* private_key, unsigned long num_bits_for_keypair);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the private key DER to fill in the public key DER
|
||||||
|
* @param private_key the private key to use
|
||||||
|
* @reutrns true(1) on success
|
||||||
|
*/
|
||||||
|
int libp2p_crypto_rsa_private_key_fill_public_key(struct RsaPrivateKey* private_key);
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Free resources used by RsaPrivateKey
|
* Free resources used by RsaPrivateKey
|
||||||
* @param private_key the resources
|
* @param private_key the resources
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
#ifndef PEERDEP
|
#ifndef PEERDEP
|
||||||
#define PEERDEP
|
#define PEERDEP
|
||||||
|
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "base58.h"
|
#include "libp2p/crypto/encoding/base58.h"
|
||||||
|
#include "mh/multihash.h"
|
||||||
|
#include "mh/hashes.h"
|
||||||
|
|
||||||
#define uchar unsigned char // 8-bit byte
|
#define uchar unsigned char // 8-bit byte
|
||||||
#define juint unsigned int // 32-bit word
|
#define juint unsigned int // 32-bit word
|
||||||
|
@ -165,25 +168,65 @@ void a_store_hash(unsigned char * result,unsigned char hash[])
|
||||||
strcat(result,mimi);
|
strcat(result,mimi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int PrettyID(unsigned char * pointyaddr, size_t rezbuflen,unsigned char * ID_BUF, size_t ID_BUF_SIZE)//b58 encoded ID buf
|
|
||||||
|
/**
|
||||||
|
* base58 encode a string NOTE: this also puts the prefix 'Qm' in front as the ID is a multihash
|
||||||
|
* @param pointyaddr where the results will go
|
||||||
|
* @param rezbuflen the length of the results buffer. It will also put how much was used here
|
||||||
|
* @param ID_BUF the input text (usually a SHA256 hash)
|
||||||
|
* @param ID_BUF_SIZE the input size (normally a SHA256, therefore 32 bytes)
|
||||||
|
* @returns true(1) on success
|
||||||
|
*/
|
||||||
|
int PrettyID(unsigned char * pointyaddr, size_t* rezbuflen,unsigned char * ID_BUF, size_t ID_BUF_SIZE)//b58 encoded ID buf
|
||||||
{
|
{
|
||||||
int returnstatus = 0;
|
int returnstatus = 0;
|
||||||
returnstatus = libp2p_crypto_encoding_base58_encode(ID_BUF, ID_BUF_SIZE, &pointyaddr, &rezbuflen);
|
|
||||||
|
unsigned char temp_buffer[*rezbuflen];
|
||||||
|
|
||||||
|
memset(temp_buffer, 0, *rezbuflen);
|
||||||
|
|
||||||
|
// wrap the base58 into a multihash
|
||||||
|
int retVal = mh_new(temp_buffer, MH_H_SHA2_256, ID_BUF, ID_BUF_SIZE);
|
||||||
|
if (retVal < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// base58 the multihash
|
||||||
|
returnstatus = libp2p_crypto_encoding_base58_encode(temp_buffer, strlen(temp_buffer), &pointyaddr, rezbuflen);
|
||||||
if(returnstatus == 0)
|
if(returnstatus == 0)
|
||||||
{
|
{
|
||||||
printf("\nERROR!!!!!\n");
|
printf("\nERROR!!!!!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
void ID_FromPK(char * result,unsigned char * texttohash)
|
|
||||||
|
/****
|
||||||
|
* Make a SHA256 hash of what is usually the DER formatted private key.
|
||||||
|
* @param result where to store the result. Should be 32 chars long
|
||||||
|
* @param texttohash the text to hash
|
||||||
|
* @param text_size the size of the text
|
||||||
|
*/
|
||||||
|
void ID_FromPK_non_null_terminated(char * result,unsigned char * texttohash, size_t text_size)
|
||||||
{
|
{
|
||||||
unsigned char hash[32];
|
unsigned char hash[32];
|
||||||
bzero(hash,32);
|
bzero(hash,32);
|
||||||
SHA256_CTX ctx;
|
SHA256_CTX ctx;
|
||||||
sha256_init(&ctx);
|
sha256_init(&ctx);
|
||||||
sha256_update(&ctx,texttohash,strlen(texttohash));
|
sha256_update(&ctx,texttohash,text_size);
|
||||||
sha256_final(&ctx,hash);
|
sha256_final(&ctx,hash);
|
||||||
a_store_hash(result,hash);
|
a_store_hash(result,hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
* Make a SHA256 hash of what is usually the DER formatted private key.
|
||||||
|
* @param result where to store the result. Should be 32 chars long
|
||||||
|
* @param texttohash a null terminated string of the text to hash
|
||||||
|
*/
|
||||||
|
void ID_FromPK(char * result,unsigned char * texttohash)
|
||||||
|
{
|
||||||
|
ID_FromPK_non_null_terminated(result,texttohash,strlen(texttohash));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,11 +1,11 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -O0 -I../include -I.
|
CFLAGS = -O0 -I../include -I. -I../../c-multihash/include
|
||||||
|
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
CFLAGS += -g3
|
CFLAGS += -g3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LFLAGS = -L../
|
LFLAGS = -L../ -L../../c-multihash
|
||||||
DEPS = crypto/test_base58.h crypto/test_rsa.h test_mbedtls.h
|
DEPS = crypto/test_base58.h crypto/test_rsa.h test_mbedtls.h
|
||||||
OBJS = testit.o
|
OBJS = testit.o
|
||||||
|
|
||||||
|
@ -13,9 +13,13 @@ OBJS = testit.o
|
||||||
$(CC) -c -o $@ $< $(CFLAGS)
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|
||||||
testit_libp2p: $(OBJS) $(DEPS)
|
testit_libp2p: $(OBJS) $(DEPS)
|
||||||
$(CC) -o $@ $(OBJS) $(LFLAGS) -lp2p -lm
|
$(CC) -o $@ $(OBJS) $(LFLAGS) -lp2p -lm -lmultihash
|
||||||
|
|
||||||
all: testit_libp2p
|
all_others:
|
||||||
|
cd ../crypto; make all;
|
||||||
|
cd ../thirdparty; make all;
|
||||||
|
|
||||||
|
all: all_others testit_libp2p
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "libp2p/crypto/rsa.h"
|
#include "libp2p/crypto/rsa.h"
|
||||||
#include "libp2p/crypto/encoding/base64.h"
|
#include "libp2p/crypto/encoding/base64.h"
|
||||||
#include "libp2p/crypto/encoding/x509.h"
|
#include "libp2p/crypto/encoding/x509.h"
|
||||||
|
#include "libp2p/peerutils.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* make sure we can get a DER formatted result
|
* make sure we can get a DER formatted result
|
||||||
|
@ -75,6 +77,112 @@ int test_crypto_x509_der_to_private() {
|
||||||
return private_key.D > 0;
|
return private_key.D > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_public_der_to_private_der() {
|
||||||
|
struct RsaPrivateKey private_key;
|
||||||
|
int retVal = libp2p_crypto_rsa_generate_keypair(&private_key, 2048);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (private_key.der_length == 0)
|
||||||
|
return 0;
|
||||||
|
if (private_key.der == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// copy the public DER to a temporary area, then erase it, then try to generate it again.
|
||||||
|
size_t public_der_temp_length = private_key.public_key_length;
|
||||||
|
unsigned char public_der_temp[private_key.public_key_length];
|
||||||
|
memcpy(public_der_temp, private_key.public_key_der, private_key.public_key_length);
|
||||||
|
|
||||||
|
free(private_key.public_key_der);
|
||||||
|
private_key.public_key_length = 0;
|
||||||
|
|
||||||
|
retVal = libp2p_crypto_rsa_private_key_fill_public_key(&private_key);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (public_der_temp_length != private_key.public_key_length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < public_der_temp_length; i++)
|
||||||
|
if (public_der_temp[i] != private_key.public_key_der[i])
|
||||||
|
return 0;
|
||||||
|
*/
|
||||||
|
// that didn't work... so let's try it again, to see if it is consistent
|
||||||
|
|
||||||
|
size_t public_der_temp_length2 = private_key.public_key_length;
|
||||||
|
unsigned char public_der_temp2[public_der_temp_length2];
|
||||||
|
memcpy(public_der_temp2, private_key.public_key_der, public_der_temp_length2);
|
||||||
|
|
||||||
|
free(private_key.public_key_der);
|
||||||
|
private_key.public_key_length = 0;
|
||||||
|
|
||||||
|
retVal = libp2p_crypto_rsa_private_key_fill_public_key(&private_key);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < public_der_temp_length2; i++)
|
||||||
|
if (private_key.public_key_der[i] != public_der_temp2[i])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// well, at least it is consistent.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_crypto_rsa_public_key_to_peer_id() {
|
||||||
|
// this is the base64 encoded private key from the config file
|
||||||
|
char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQDTDJBWjDzS/HxDNOHazvzH2bu9CPMVHUrrvKRdBUM5ansL6/CC3MVZ6HVm4O6QHRapN6EF2CbrTgI4KBOXIL125Xo8MlROnyfXYk3O5q2tgwL/MbW8kXjtkyCfBak7MUoLOdLU7Svg0gkl3l+uDAiDcCLnwJVcFfq9ch6z4wMOhYJqE5dtx0uXxn6IuKWl1B69FTvBXCc0thw8Rw54b941FDcsBH5ttV9mRNCJym3poZ5qalNgXlxoIIB+PUx5QD+aq7KMJdpAX8HkapBntCOahP/QUceRmma0grlZLeYkH6/oi/hIrM6se3KUZ+F6tBuDFys8UAZy/X2BCUbKjbxtAgMBAAECggEANWfQfpYuLhXGPBt9q6kFPm1SnJtPJ+CpvM2XqhJS2IyhZnrl+bd0GTRBwS7aL42s1lVFYf04nAK5fQxnKK8YQqX/MIxr2RldM5ukpN6qxGWKtJkXrAgD2dqJPrRoBpqKahzPxSHfIJ0Fw5dqDtjsrpYJvyt0oEDPmnDuZAbmFx4sJqnesPNhKxtRMBx1+yxGVuRVJjHcqAgqPqwNiuoMEaYMY+G9yzT6vza8ovCpbX7BBIgM5fAT9PD8TBG//Vu9THvj/ZomiVG2qv6RL0qQyVb+DUzPZz1amBsSvahtXCl72jA3JwAZ943RxSR66P934S0ashkVwLUi46z/EAbJ4QKBgQDojGIO07BEVL2+7VxlGL9XGZQp4Y3qlhh2zDDQGwkCq/KQ+BdNYWitPwqRl9GqFLgpmeQIhyHTOa/IThx+AXGKVQ24ROH+skUs4IbO6R3qY7BKtb5lkZE/Yln09x70BBngUYAzh/rtnsXO3cl1x2XDDqUbCwlGcDAs8Jh/6UnvQwKBgQDoVSQs7Uq9MJCGIUM2bixX89tHzSxq5mn9wMD3/XRVfT5Ua8YkYBuzcmlcT39N7L5BwuyFqX3Vi7lv/Ya/qaQP6XkrZ8W1OAaTlYewfE5ZgknJqSpXcNWhABKeNmqndvqyQ/8HNCv/j8AdraGB2DGO57Xso5J0CQ43W/U9+QIyjwKBgHLL2hw3o+wXaRO3WMUPUmVM2zdRgR0suybp5a7Vqb0H5NZrohUw4NulIzJ8H6Q2VjMzJL6Q9sGu2HepF6ecTtBa7ErqtiVlG4Dr1aCOs5XhYEWBMlwxX+JKSt4Cn+UVoTB7Cy5lEhn7JurX0Xuy0ylXMWoIKKv89cs5eg6quzTBAoGAaq9eEztLjKCWXOE9SetBdYnG8aunb9cqaJlwgu/h0bfXPVDYBbAUSEyLURY4MQI7Q1tM3Pu9iqfEmUZj7/LoIV5mg6X9RX/alT6etk3+dF+9nlqN1OU9U9cCtZ/rTcb2y5EptJcidRH/eCFY/pTV/PcttOJPx/S4kHcroC+N8MUCgYEA6DA5QHxHfNN6Nxv+pEzy2DIxFe9RrBxS+KPBsra1C8jgdeMf4EmfU0Nox92V0q0bRrD5ztqQwSONI0hSRb1iiMWR6MuFnAFajUJfASjjIlZ6nIQjQslI7vjlvYyyHS/p/Codxap+yJlTLWwVEOXp2D9pWwiMq1xEyf0TH1BosvM=";
|
||||||
|
// this is the peer id from the config file
|
||||||
|
char* orig_peer_id = "QmRskXriTSRjAftYX7QG1i1jAhouz5AHaLYZKNhEWRu5Fq";
|
||||||
|
size_t orig_peer_id_size = strlen(orig_peer_id);
|
||||||
|
// if we take the private key, retrieve the public key, hash it, we should come up with the peer id
|
||||||
|
|
||||||
|
// 1) take the private key and turn it back into bytes (decode base 64)
|
||||||
|
size_t decode_base64_size = libp2p_crypto_encoding_base64_decode_size(strlen(orig_priv_key));
|
||||||
|
unsigned char decode_base64[decode_base64_size];
|
||||||
|
memset(decode_base64, 0, decode_base64_size);
|
||||||
|
unsigned char* ptr = decode_base64;
|
||||||
|
|
||||||
|
int retVal = libp2p_crypto_encoding_base64_decode(orig_priv_key, strlen(orig_priv_key), ptr, decode_base64_size, &decode_base64_size);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// the first 5 bytes [0-4] are protobuf metadata before the DER encoded private key
|
||||||
|
// byte 0 is "Tag 1 which is a varint"
|
||||||
|
// byte 1 is the value of the varint
|
||||||
|
// byte 2 is "Tag 2 which is a type 2, length delimited field"
|
||||||
|
// bytes 3 & 4 is a varint with the value of 1191, which is the number of bytes that follow
|
||||||
|
|
||||||
|
// 2) take the bytes of the private key and turn it back into a private key struct
|
||||||
|
struct RsaPrivateKey private_key = {0};
|
||||||
|
retVal = libp2p_crypto_encoding_x509_der_to_private_key(&decode_base64[5], decode_base64_size - 5, &private_key);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// 2b) take the private key and fill in the public key DER
|
||||||
|
retVal = libp2p_crypto_rsa_private_key_fill_public_key(&private_key);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// 3) grab the public key, hash it, then base58 it
|
||||||
|
unsigned char hashed[32];
|
||||||
|
ID_FromPK_non_null_terminated(hashed, private_key.public_key_der, private_key.public_key_length);
|
||||||
|
size_t final_id_size = 1600;
|
||||||
|
unsigned char final_id[final_id_size];
|
||||||
|
memset(final_id, 0, final_id_size);
|
||||||
|
retVal = PrettyID(final_id, &final_id_size, hashed, 32);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// 4) compare results
|
||||||
|
if (orig_peer_id_size != final_id_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strncmp(orig_peer_id, final_id, final_id_size) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* test_rsa_h */
|
#endif /* test_rsa_h */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
#include "crypto/test_rsa.h"
|
#include "crypto/test_rsa.h"
|
||||||
#include "crypto/test_base58.h"
|
#include "crypto/test_base58.h"
|
||||||
#include "test_mbedtls.h"
|
#include "test_mbedtls.h"
|
||||||
|
@ -16,10 +17,11 @@ int testit(const char* name, int (*func)(void)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
testit("test_public_der_to_private_der", test_public_der_to_private_der);
|
||||||
testit("test_mbedtls_varint_128_binary", test_mbedtls_varint_128_binary);
|
testit("test_mbedtls_varint_128_binary", test_mbedtls_varint_128_binary);
|
||||||
testit("test_mbedtls_varint_128_string", test_mbedtls_varint_128_string);
|
testit("test_mbedtls_varint_128_string", test_mbedtls_varint_128_string);
|
||||||
testit("test_crypto_rsa_private_key_der", test_crypto_rsa_private_key_der);
|
testit("test_crypto_rsa_private_key_der", test_crypto_rsa_private_key_der);
|
||||||
//testit("test_crypto_x509_private_to_der", test_crypto_x509_private_to_der);
|
testit("test_crypto_rsa_public_key_to_peer_id", test_crypto_rsa_public_key_to_peer_id);
|
||||||
testit("test_crypto_x509_der_to_private2", test_crypto_x509_der_to_private2);
|
testit("test_crypto_x509_der_to_private2", test_crypto_x509_der_to_private2);
|
||||||
testit("test_crypto_x509_der_to_private", test_crypto_x509_der_to_private);
|
testit("test_crypto_x509_der_to_private", test_crypto_x509_der_to_private);
|
||||||
//testit("test_multihash_encode", test_multihash_encode);
|
//testit("test_multihash_encode", test_multihash_encode);
|
||||||
|
|
Loading…
Reference in a new issue