substantial work towards implementing BK field in rhizome manifests.

This commit is contained in:
gardners 2012-05-15 17:24:25 +09:30
parent 17370b3464
commit 525d3c4154
6 changed files with 82 additions and 27 deletions

View File

@ -1044,9 +1044,11 @@ int app_config_get(int argc, const char *const *argv, struct command_line_option
int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_option *o)
{
const char *filepath, *manifestpath;
const char *filepath, *manifestpath,*authorisingSid;
cli_arg(argc, argv, o, "filepath", &filepath, NULL, "");
cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "");
cli_arg(argc, argv, o, "sid", &authorisingSid,NULL,"");
/* Ensure the Rhizome database exists and is open */
if (create_serval_instance_dir() == -1)
return -1;
@ -1085,7 +1087,8 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
255, // ttl - XXX should read from somewhere
manifest_file_supplied, // int verifyP
1, // int checkFileP
1 // int signP
1, // int signP
authorisingSid // SID of claiming author as hex, so that they can modify the bundle later
);
if (ret == -1)
return WHY("Manifest not added to Rhizome database");

View File

@ -53,7 +53,10 @@ int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, cons
/* Add the manifest and its associated file to the Rhizome database. */
rhizome_manifest *dupm;
int ret = rhizome_add_manifest(m, &dupm, filename, groups, ttl, verifyP, checkFileP, signP);
int ret = rhizome_add_manifest(m, &dupm, filename, groups, ttl,
verifyP, checkFileP, signP,
NULL /* don't specify author for manifests
received via mesh */);
unlink(filename);
if (ret == -1) {
unlink(manifestname);
@ -137,7 +140,8 @@ int rhizome_add_manifest(rhizome_manifest *m_in,
int ttl,
int verifyP, // verify that file's hash is consistent with manifest
int checkFileP,
int signP
int signP,
const char *author
)
{
if (m_out) *m_out = NULL;
@ -246,7 +250,7 @@ int rhizome_add_manifest(rhizome_manifest *m_in,
}
/* Check if we know its private key */
rhizome_hex_to_bytes(id, m_in->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
if (!rhizome_find_keypair_bytes(m_in->cryptoSignPublic, m_in->cryptoSignSecret))
if (!rhizome_find_privatekey(m_in))
m_in->haveSecret=1;
} else {
/* The manifest had no ID (256 bit random string being a public key in the NaCl CryptoSign
@ -255,9 +259,19 @@ int rhizome_add_manifest(rhizome_manifest *m_in,
/* 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. */
extra bytes. */
id = rhizome_bytes_to_hex(m_in->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
rhizome_manifest_set(m_in, "id", id);
if (author) {
/* Set the BK using the provided authorship information.
Serval Security Framework defines BK as being:
BK = privateKey XOR sha512(RS##BID), where BID = cryptoSignPublic,
and RS is the rhizome secret for the specified author.
The nice thing about this specification is that:
privateKey = BK XOR sha512(RS##BID), so the same function can be used
to encrypt and decrypt the BK field. */
}
}
/* Add group memberships */

View File

@ -199,14 +199,13 @@ int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, cons
int verifyP, int checkFileP, int signP);
int rhizome_add_manifest(rhizome_manifest *m_in, rhizome_manifest **m_out, const char *filename,
char *groups[], int ttl,
int verifyP, int checkFileP, int signP);
int verifyP, int checkFileP, int signP,
const char *author);
int rhizome_manifest_finalise(rhizome_manifest *m,int signP);
char *rhizome_bytes_to_hex(unsigned char *in,int byteCount);
int rhizome_hex_to_bytes(const 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);
int rhizome_find_privatekey(rhizome_manifest *m);
rhizome_signature *rhizome_sign_hash(rhizome_manifest *m);
int rhizome_server_free_http_request(rhizome_http_request *r);
int rhizome_server_close_http_request(int i);
int rhizome_server_http_send_bytes(int rn,rhizome_http_request *r);
@ -236,3 +235,7 @@ int rhizome_fetching_get_fds(struct pollfd *fds,int *fdcount,int fdmax);
int rhizome_manifest_version_cache_lookup(rhizome_manifest *m);
int rhizome_manifest_version_cache_store(rhizome_manifest *m);
int monitor_announce_bundle(rhizome_manifest *m);
int rhizome_bk_xor(const char *author,
unsigned char bid[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES],
unsigned char bkin[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES],
unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES]);

View File

@ -145,14 +145,7 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
} else m->selfSigned=1;
}
}
/* Check for a BK entry that allows us to recover the private key for this bundle's ID.
The challenge is that BK's are designed to offer plausible deniability, in that the
manifest provides nothing that would allow an adversary, without posession of the creator's
keyring, to be able to prove that any given identity is the creator of the file.
*/
if (debug&DEBUG_RHIZOME)
fprintf(stderr, "Group membership determination not implemented (see which signatories are groups? what about manifests signed by groups we don't yet know about?)\n");
}
@ -423,7 +416,7 @@ int rhizome_manifest_pack_variables(rhizome_manifest *m)
/* Sign this manifest using our own private CryptoSign key */
int rhizome_manifest_sign(rhizome_manifest *m)
{
rhizome_signature *sig=rhizome_sign_hash(m->manifesthash,m->cryptoSignPublic);
rhizome_signature *sig=rhizome_sign_hash(m);
if (!sig) return WHY("rhizome_sign_hash() failed.");

View File

@ -41,10 +41,11 @@ int rhizome_manifest_createid(rhizome_manifest *m)
{
m->haveSecret=1;
int r=crypto_sign_edwards25519sha512batch_keypair(m->cryptoSignPublic,m->cryptoSignSecret);
if (!r) return rhizome_store_keypair_bytes(m->cryptoSignPublic,m->cryptoSignSecret);
if (!r) return 0;
return WHY("Failed to create keypair for manifest ID.");
}
#ifdef DEPRECATED
int rhizome_store_keypair_bytes(unsigned char *p,unsigned char *s) {
/* XXX TODO Secrets should be encrypted using a keyring password. */
if (sqlite_exec_int64("INSERT INTO KEYPAIRS(public,private) VALUES('%s','%s');",
@ -79,12 +80,56 @@ int rhizome_find_keypair_bytes(unsigned char *p,unsigned char *s) {
sqlite3_finalize(statement);
return WHY("Could not find matching secret key.");
}
#endif
rhizome_signature *rhizome_sign_hash(unsigned char *hash,unsigned char *publicKeyBytes)
int rhizome_bk_xor(const char *author,
unsigned char bid[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES],
unsigned char bkin[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES],
unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES])
{
if (crypto_sign_edwards25519sha512batch_SECRETKEYBYTES>
crypto_hash_sha512_BYTES)
return WHY("BK needs to be longer than it can be");
unsigned char authorSid[SID_SIZE];
if (stowSid(authorSid,0,author)) return WHY("stowSid() failed");
int cn=0,in=0,kp=0;
if (!keyring_find_sid(keyring,&cn,&in,&kp,authorSid))
return WHY("keyring_find_sid() couldn't find that SID. Have you unlocked that identity?");
for(kp=0;kp<keyring->contexts[cn]->identities[in]->keypair_count;kp++)
if (keyring->contexts[cn]->identities[in]->keypairs[kp]->type==KEYTYPE_RHIZOME)
break;
if (kp>=keyring->contexts[cn]->identities[in]->keypair_count)
return WHY("Identity has no Rhizome Secret");
int rs_len=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key_len;
unsigned char *rs=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key;
if (rs_len<16||rs_len>1024)
return WHYF("Rhizome Secret is too short or too long (length=%d)",rs_len);
int combined_len=rs_len+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES;
unsigned char buffer[combined_len];
bcopy(&rs[0],&buffer[0],rs_len);
bcopy(&bid[0],&buffer[rs_len],crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
unsigned char hash[crypto_hash_sha512_BYTES];
crypto_hash_sha512(hash,buffer,combined_len);
int i;
for(i=0;i<crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES;i++)
bkout[i]=bkin[i]^hash[i];
bzero(&buffer[0],combined_len);
bzero(&hash[0],crypto_hash_sha512_BYTES);
return 0;
}
rhizome_signature *rhizome_sign_hash(rhizome_manifest *m)
{
unsigned char *hash=m->manifesthash;
unsigned char *publicKeyBytes=m->cryptoSignPublic;
unsigned char secretKeyBytes[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES];
if (rhizome_find_keypair_bytes(publicKeyBytes,secretKeyBytes))
if (rhizome_find_privatekey(m))
{
WHY("Cannot find secret key to sign manifest data.");
return NULL;

View File

@ -399,11 +399,8 @@ int rhizome_store_bundle(rhizome_manifest *m, const char *associated_filename)
manifestid, m->version, gettime_ms());
if (m->haveSecret) {
if (rhizome_store_keypair_bytes(m->cryptoSignPublic,m->cryptoSignSecret))
{
WHY("*** Insert into manifests failed (-1).");
return WHY("Failed to store key pair.");
}
/* We used to store the secret in the database, but we don't anymore, as we use
the BK field in the manifest. So nothing to do here. */
} else {
/* We don't have the secret for this manifest, so only allow updates if
the self-signature is valid */