mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-21 01:42:18 +00:00
Further work on getting signatures and signed manifests working.
Some work on updating existing manifests, although some cascading consequences need addressing (in particular checking if the file associated with the old version of the manifest still needs to hang about, and if so, whether its highest priority has changed).
This commit is contained in:
parent
4719281f03
commit
745cade469
110
rhizome.c
110
rhizome.c
@ -325,12 +325,27 @@ int rhizome_bundle_import(char *bundle,char *groups[],int verifyP, int checkFile
|
||||
if (rhizome_manifest_get(m,"id",buffer)!=0) {
|
||||
/* No bundle id (256 bit random string being a public key in the NaCl CryptoSign crypto system),
|
||||
so create one, and keep the private key handy. */
|
||||
printf("manifest does not have an id\n");
|
||||
rhizome_manifest_createid(m);
|
||||
/* The ID is implicit in transit, but we need to store it in the file,
|
||||
so that reimporting manifests on receiver nodes works easily.
|
||||
We might implement something that strips the id variable out of the
|
||||
manifest when sending it, or some other scheme to avoid sending all
|
||||
the extra bytes. */
|
||||
rhizome_manifest_set(m,"id",rhizome_bytes_to_hex(m->cryptoSignPublic,crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES));
|
||||
} else {
|
||||
/* An ID was specified, so look for the private key if we have it stowed away */
|
||||
/* An ID was specified, so remember it, and look for the private key if
|
||||
we have it stowed away */
|
||||
rhizome_hex_to_bytes(buffer,m->cryptoSignPublic,
|
||||
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
|
||||
if (!rhizome_find_keypair_bytes(m->cryptoSignPublic,m->cryptoSignSecret))
|
||||
m->haveSecret=1;
|
||||
}
|
||||
dump("public key",m->cryptoSignPublic,
|
||||
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
|
||||
dump("secret key",m->cryptoSignSecret,
|
||||
crypto_sign_edwards25519sha512batch_SECRETKEYBYTES);
|
||||
|
||||
rhizome_manifest_set(m,"filehash",hexhash);
|
||||
if (rhizome_manifest_get(m,"version",NULL)!=0)
|
||||
/* Version not set, so set one */
|
||||
@ -366,7 +381,7 @@ int i;
|
||||
/* Okay, it is written, and can be put directly into the rhizome database now */
|
||||
int r=rhizome_store_bundle(m,filename);
|
||||
if (!r) {
|
||||
unlink(manifestname);
|
||||
// unlink(manifestname);
|
||||
unlink(filename);
|
||||
|
||||
return 0;
|
||||
@ -440,14 +455,13 @@ rhizome_manifest *rhizome_read_manifest_file(char *filename)
|
||||
|
||||
/* Calculate hash of the text part of the file, as we need to couple this with
|
||||
each signature block to */
|
||||
unsigned char manifest_hash[crypto_hash_sha512_BYTES];
|
||||
crypto_hash_sha512(manifest_hash,m->manifestdata,end_of_text);
|
||||
crypto_hash_sha512(m->manifesthash,m->manifestdata,end_of_text);
|
||||
|
||||
/* Read signature blocks from file.
|
||||
XXX - What additional information/restrictions should the
|
||||
signatures have? start/expiry times? geo bounding box?
|
||||
Those elements all need to be included in the hash */
|
||||
WHY("Signature verification not implemented");
|
||||
WHY("Signature reading not implemented");
|
||||
|
||||
WHY("Group membership signature reading not implemented (are we still doing it this way?)");
|
||||
|
||||
@ -585,15 +599,34 @@ int rhizome_manifest_pack_variables(rhizome_manifest *m)
|
||||
m->vars[i],m->values[i]);
|
||||
ofs+=strlen((char *)&m->manifestdata[ofs]);
|
||||
}
|
||||
m->manifestdata[ofs++]=0x00;
|
||||
m->manifest_bytes=ofs;
|
||||
|
||||
/* Recalculate hash */
|
||||
crypto_hash_sha512(m->manifesthash,m->manifestdata,m->manifest_bytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sign this manifest using our own private CryptoSign key */
|
||||
int rhizome_manifest_sign(rhizome_manifest *m)
|
||||
{
|
||||
return WHY("Not implemented.");
|
||||
rhizome_signature *sig=rhizome_sign_hash(m->manifesthash,m->cryptoSignPublic);
|
||||
|
||||
if (!sig) return WHY("rhizome_sign_hash() failed.");
|
||||
|
||||
/* Append signature to end of manifest data */
|
||||
if (sig->signatureLength+m->manifest_bytes>MAX_MANIFEST_BYTES) {
|
||||
free(sig);
|
||||
return WHY("Manifest plus signatures is too long.");
|
||||
}
|
||||
|
||||
bcopy(&sig->signature[0],&m->manifestdata[m->manifest_bytes],sig->signatureLength);
|
||||
|
||||
m->manifest_bytes+=sig->signatureLength;
|
||||
|
||||
free(sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rhizome_write_manifest_file(rhizome_manifest *m,char *filename)
|
||||
@ -610,7 +643,9 @@ int rhizome_write_manifest_file(rhizome_manifest *m,char *filename)
|
||||
int rhizome_manifest_createid(rhizome_manifest *m)
|
||||
{
|
||||
m->haveSecret=1;
|
||||
return crypto_sign_edwards25519sha512batch_keypair(m->cryptoSignPublic,m->cryptoSignSecret);
|
||||
int r=crypto_sign_edwards25519sha512batch_keypair(m->cryptoSignPublic,m->cryptoSignSecret);
|
||||
if (!r) return rhizome_store_keypair_bytes(m->cryptoSignPublic,m->cryptoSignSecret);
|
||||
return WHY("Failed to create keypair for manifest ID.");
|
||||
}
|
||||
|
||||
int rhizome_store_keypair_bytes(unsigned char *p,unsigned char *s) {
|
||||
@ -638,7 +673,7 @@ int rhizome_find_keypair_bytes(unsigned char *p,unsigned char *s) {
|
||||
if (sqlite3_column_type(statement,0)==SQLITE_TEXT) {
|
||||
const unsigned char *hex=sqlite3_column_text(statement,0);
|
||||
rhizome_hex_to_bytes((char *)hex,s,
|
||||
crypto_sign_edwards25519sha512batch_SECRETKEYBYTES);
|
||||
crypto_sign_edwards25519sha512batch_SECRETKEYBYTES*2);
|
||||
/* XXX TODO Decrypt secret using a keyring password */
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
@ -676,6 +711,19 @@ int rhizome_store_bundle(rhizome_manifest *m,char *associated_filename)
|
||||
|
||||
if (!m->finalised) return WHY("Manifest was not finalised");
|
||||
|
||||
/* remove any old version of the manifest */
|
||||
if (sqlite_exec_int64("SELECT COUNT(*) MANIFESTS WHERE id='%s';",
|
||||
rhizome_bytes_to_hex(m->cryptoSignPublic,crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES))>0)
|
||||
{
|
||||
/* Manifest already exists.
|
||||
Remove old manifest entry, and replace with new one.
|
||||
But we do need to check if the file referenced by the old one is still needed,
|
||||
and if it's priority is right */
|
||||
sqlite_exec_int64("DELETE FROM MANIFESTS WHERE id='%s';",
|
||||
rhizome_bytes_to_hex(m->cryptoSignPublic,crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES));
|
||||
WHY("Need to examine the manifestfiles row for the deleted entry (id still matches, so we can find it, and see if it is still needed, or if its priority has changed). Then delete the old manifestfiles row.");
|
||||
}
|
||||
|
||||
/* Store manifest */
|
||||
snprintf(sqlcmd,1024,"INSERT INTO MANIFESTS(id,manifest,version,inserttime) VALUES('%s',?,%lld,%lld);",
|
||||
rhizome_bytes_to_hex(m->cryptoSignPublic,crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES),
|
||||
@ -1060,9 +1108,9 @@ char *rhizome_bytes_to_hex(unsigned char *in,int byteCount)
|
||||
rse_rotor++;
|
||||
rse_rotor&=3;
|
||||
|
||||
for(i=0;i<byteCount;i++)
|
||||
for(i=0;i<byteCount*2;i++)
|
||||
{
|
||||
int d=nybltochar(in[i>>1]>>(4-4*(i&1)));
|
||||
int d=nybltochar((in[i>>1]>>(4-4*(i&1)))&0xf);
|
||||
rse_out[rse_rotor][i]=d;
|
||||
}
|
||||
rse_out[rse_rotor][i]=0;
|
||||
@ -1073,7 +1121,7 @@ int chartonybl(int c)
|
||||
{
|
||||
if (c>='A'&&c<='F') return 0x0a+(c-'A');
|
||||
if (c>='a'&&c<='f') return 0x0a+(c-'a');
|
||||
if (c>='0'&&c<='9') return 0x0a+(c-'0');
|
||||
if (c>='0'&&c<='9') return 0x00+(c-'0');
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1090,3 +1138,43 @@ int rhizome_hex_to_bytes(char *in,unsigned char *out,int hexChars)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
rhizome_signature *rhizome_sign_hash(unsigned char *hash,unsigned char *publicKeyBytes)
|
||||
{
|
||||
unsigned char secretKeyBytes[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES];
|
||||
|
||||
if (rhizome_find_keypair_bytes(publicKeyBytes,secretKeyBytes))
|
||||
{
|
||||
WHY("Cannot find secret key to sign manifest data.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Signature is formed by running crypto_sign_edwards25519sha512batch() on the
|
||||
hash of the manifest. The signature actually contains the hash, so to save
|
||||
space we cut the hash out of the signature. */
|
||||
unsigned char signatureBuffer[crypto_sign_edwards25519sha512batch_BYTES+crypto_hash_sha512_BYTES];
|
||||
unsigned long long sigLen=0;
|
||||
int mLen=crypto_hash_sha512_BYTES;
|
||||
|
||||
int r=crypto_sign_edwards25519sha512batch(signatureBuffer,&sigLen,
|
||||
&hash[0],mLen,secretKeyBytes);
|
||||
if (r) {
|
||||
WHY("crypto_sign() failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rhizome_signature *out=calloc(sizeof(rhizome_signature),1);
|
||||
|
||||
/* Here we use knowledge of the internal structure of the signature block
|
||||
to remove the hash, since that is implicitly transported, thus reducing the
|
||||
actual signature size down to 64 bytes.
|
||||
We do then need to add the public key of the signatory on. */
|
||||
bcopy(&signatureBuffer[0],&out->signature[1],32);
|
||||
bcopy(&signatureBuffer[96],&out->signature[33],32);
|
||||
bcopy(&publicKeyBytes[0],&out->signature[65],crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
|
||||
out->signatureLength=65+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES;
|
||||
out->signature[0]=out->signatureLength;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,12 @@
|
||||
#include "sha2.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
typedef struct rhizome_signature {
|
||||
unsigned char signature[crypto_sign_edwards25519sha512batch_BYTES
|
||||
+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
|
||||
int signatureLength;
|
||||
} rhizome_signature;
|
||||
|
||||
#define MAX_MANIFEST_VARS 256
|
||||
#define MAX_MANIFEST_BYTES 8192
|
||||
typedef struct rhizome_manifest {
|
||||
@ -85,3 +91,6 @@ int rhizome_bundle_import(char *bundle,char *groups[],int verifyP, int checkFile
|
||||
int rhizome_manifest_finalise(rhizome_manifest *m,int signP);
|
||||
char *rhizome_bytes_to_hex(unsigned char *in,int byteCount);
|
||||
int rhizome_hex_to_bytes(char *in,unsigned char *out,int hexChars);
|
||||
int rhizome_store_keypair_bytes(unsigned char *p,unsigned char *s);
|
||||
int rhizome_find_keypair_bytes(unsigned char *p,unsigned char *s);
|
||||
rhizome_signature *rhizome_sign_hash(unsigned char *hash,unsigned char *publicKeyBytes);
|
||||
|
Loading…
x
Reference in New Issue
Block a user