Hush Full Node software. We were censored from Github, this is where all development happens now.
https://hush.is
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
6.1 KiB
184 lines
6.1 KiB
// Copyright (c) 2016-2020 The Hush developers
|
|
/******************************************************************************
|
|
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
* *
|
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
* the top-level directory of this distribution for the individual copyright *
|
|
* holder information and the developer policies on copyright and licensing. *
|
|
* *
|
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
* SuperNET software, including this file may be copied, modified, propagated *
|
|
* or distributed except according to the terms contained in the LICENSE file *
|
|
* *
|
|
* Removal or modification of this copyright notice is prohibited. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#include "asn/Condition.h"
|
|
#include "asn/Fulfillment.h"
|
|
#include "asn/Ed25519FingerprintContents.h"
|
|
#include "asn/OCTET_STRING.h"
|
|
#include "include/cJSON.h"
|
|
#include "include/ed25519/src/ed25519.h"
|
|
#include "cryptoconditions.h"
|
|
|
|
|
|
struct CCType CC_Ed25519Type;
|
|
|
|
|
|
static void ed25519Fingerprint(const CC *cond, uint8_t *out) {
|
|
Ed25519FingerprintContents_t *fp = calloc(1, sizeof(Ed25519FingerprintContents_t));
|
|
OCTET_STRING_fromBuf(&fp->publicKey, cond->publicKey, 32);
|
|
hashFingerprintContents(&asn_DEF_Ed25519FingerprintContents, fp, out);
|
|
}
|
|
|
|
|
|
int ed25519Verify(CC *cond, CCVisitor visitor) {
|
|
if (cond->type->typeId != CC_Ed25519Type.typeId) return 1;
|
|
// TODO: test failure mode: empty sig / null pointer
|
|
return ed25519_verify(cond->signature, visitor.msg, visitor.msgLength, cond->publicKey);
|
|
}
|
|
|
|
|
|
static int cc_ed25519VerifyTree(const CC *cond, const unsigned char *msg, size_t msgLength) {
|
|
CCVisitor visitor = {&ed25519Verify, msg, msgLength, NULL};
|
|
return cc_visit((CC*) cond, visitor);
|
|
}
|
|
|
|
|
|
/*
|
|
* Signing data
|
|
*/
|
|
typedef struct CCEd25519SigningData {
|
|
unsigned char *pk;
|
|
unsigned char *skpk;
|
|
int nSigned;
|
|
} CCEd25519SigningData;
|
|
|
|
|
|
/*
|
|
* Visitor that signs an ed25519 condition if it has a matching public key
|
|
*/
|
|
static int ed25519Sign(CC *cond, CCVisitor visitor) {
|
|
if (cond->type->typeId != CC_Ed25519Type.typeId) return 1;
|
|
CCEd25519SigningData *signing = (CCEd25519SigningData*) visitor.context;
|
|
if (0 != memcmp(cond->publicKey, signing->pk, 32)) return 1;
|
|
if (!cond->signature) cond->signature = calloc(1,64);
|
|
ed25519_sign(cond->signature, visitor.msg, visitor.msgLength,
|
|
signing->pk, signing->skpk);
|
|
signing->nSigned++;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Sign ed25519 conditions in a tree
|
|
*/
|
|
int cc_signTreeEd25519(CC *cond, const unsigned char *privateKey, const unsigned char *msg,
|
|
const size_t msgLength) {
|
|
unsigned char pk[32], skpk[64];
|
|
ed25519_create_keypair(pk, skpk, privateKey);
|
|
|
|
CCEd25519SigningData signing = {pk, skpk, 0};
|
|
CCVisitor visitor = {&ed25519Sign, (unsigned char*)msg, msgLength, &signing};
|
|
cc_visit(cond, visitor);
|
|
return signing.nSigned;
|
|
}
|
|
|
|
|
|
static unsigned long ed25519Cost(const CC *cond) {
|
|
return 131072;
|
|
}
|
|
|
|
|
|
static CC *ed25519FromJSON(const cJSON *params, char *err) {
|
|
size_t binsz;
|
|
|
|
cJSON *pk_item = cJSON_GetObjectItem(params, "publicKey");
|
|
if (!cJSON_IsString(pk_item)) {
|
|
strcpy(err, "publicKey must be a string");
|
|
return NULL;
|
|
}
|
|
unsigned char *pk = base64_decode(pk_item->valuestring, &binsz);
|
|
if (32 != binsz) {
|
|
strcpy(err, "publicKey has incorrect length");
|
|
free(pk);
|
|
return NULL;
|
|
}
|
|
|
|
cJSON *signature_item = cJSON_GetObjectItem(params, "signature");
|
|
unsigned char *sig = NULL;
|
|
if (signature_item && !cJSON_IsNull(signature_item)) {
|
|
if (!cJSON_IsString(signature_item)) {
|
|
strcpy(err, "signature must be null or a string");
|
|
return NULL;
|
|
}
|
|
sig = base64_decode(signature_item->valuestring, &binsz);
|
|
if (64 != binsz) {
|
|
strcpy(err, "signature has incorrect length");
|
|
free(sig);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
CC *cond = cc_new(CC_Ed25519);
|
|
cond->publicKey = pk;
|
|
cond->signature = sig;
|
|
return cond;
|
|
}
|
|
|
|
|
|
static void ed25519ToJSON(const CC *cond, cJSON *params) {
|
|
unsigned char *b64 = base64_encode(cond->publicKey, 32);
|
|
cJSON_AddItemToObject(params, "publicKey", cJSON_CreateString(b64));
|
|
free(b64);
|
|
if (cond->signature) {
|
|
b64 = base64_encode(cond->signature, 64);
|
|
cJSON_AddItemToObject(params, "signature", cJSON_CreateString(b64));
|
|
free(b64);
|
|
}
|
|
}
|
|
|
|
|
|
static CC *ed25519FromFulfillment(const Fulfillment_t *ffill) {
|
|
CC *cond = cc_new(CC_Ed25519);
|
|
cond->publicKey = calloc(1,32);
|
|
memcpy(cond->publicKey, ffill->choice.ed25519Sha256.publicKey.buf, 32);
|
|
cond->signature = calloc(1,64);
|
|
memcpy(cond->signature, ffill->choice.ed25519Sha256.signature.buf, 64);
|
|
return cond;
|
|
}
|
|
|
|
|
|
static Fulfillment_t *ed25519ToFulfillment(const CC *cond) {
|
|
if (!cond->signature) {
|
|
return NULL;
|
|
}
|
|
Fulfillment_t *ffill = calloc(1, sizeof(Fulfillment_t));
|
|
ffill->present = Fulfillment_PR_ed25519Sha256;
|
|
Ed25519Sha512Fulfillment_t *ed2 = &ffill->choice.ed25519Sha256;
|
|
OCTET_STRING_fromBuf(&ed2->publicKey, cond->publicKey, 32);
|
|
OCTET_STRING_fromBuf(&ed2->signature, cond->signature, 64);
|
|
return ffill;
|
|
}
|
|
|
|
|
|
int ed25519IsFulfilled(const CC *cond) {
|
|
return cond->signature > 0;
|
|
}
|
|
|
|
|
|
static void ed25519Free(CC *cond) {
|
|
free(cond->publicKey);
|
|
if (cond->signature) {
|
|
free(cond->signature);
|
|
}
|
|
}
|
|
|
|
|
|
static uint32_t ed25519Subtypes(const CC *cond) {
|
|
return 0;
|
|
}
|
|
|
|
|
|
struct CCType CC_Ed25519Type = { 4, "ed25519-sha-256", Condition_PR_ed25519Sha256, 0, &ed25519Fingerprint, &ed25519Cost, &ed25519Subtypes, &ed25519FromJSON, &ed25519ToJSON, &ed25519FromFulfillment, &ed25519ToFulfillment, &ed25519IsFulfilled, &ed25519Free };
|
|
|