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

// 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 };