// sign the hash of a message, adding the signature to the end of the message buffer. int crypto_sign_message(struct keyring_identity *identity, unsigned char *content, size_t buffer_len, size_t *content_len) { if (*content_len + SIGNATURE_BYTES > buffer_len) return WHYF("Insufficient space in message buffer to add signature. %zu, need %zu",buffer_len, *content_len + SIGNATURE_BYTES); struct keypair *key = keyring_find_sas_private(keyring, identity); if (!key) return WHY("Could not find signing key"); unsigned char hash[crypto_hash_sha512_BYTES]; crypto_hash_sha512(hash, content, *content_len); int sig_length = SIGNATURE_BYTES; int ret=crypto_create_signature(key->private_key, hash, crypto_hash_sha512_BYTES, &content[*content_len], &sig_length); *content_len+=sig_length; return ret; }
static int serval_create_signature(unsigned char *key, const unsigned char *msg, const size_t msg_len, unsigned char *sig_buffer, const size_t sig_size) { unsigned long long sig_length = SIGNATURE_BYTES; CHECK(sig_size >= msg_len + SIGNATURE_BYTES,"Signature buffer too small"); unsigned char hash[crypto_hash_sha512_BYTES]; crypto_hash_sha512(hash, msg, msg_len); // create sha512 hash of message, which will then be signed memcpy(sig_buffer,msg,msg_len); if (crypto_create_signature(key, hash, crypto_hash_sha512_BYTES, &sig_buffer[msg_len], &sig_length) != 0) // create signature of message hash, append it to end of message return 0; return 1; error: return 0; }
static int serval_create_signature(svl_crypto_ctx *ctx) { CHECK(ctx && ctx->sas_private[0] && ctx->msg && ctx->msg_len,"Invalid ctx"); unsigned long long sig_length = SIGNATURE_BYTES; unsigned char hash[crypto_hash_sha512_BYTES]; // create sha512 hash of message, which will then be signed crypto_hash_sha512(hash, ctx->msg, ctx->msg_len); // create signature of message hash, append it to end of message int sig_ret = crypto_create_signature(ctx->sas_private, hash, crypto_hash_sha512_BYTES, ctx->signature, &sig_length); if (sig_ret != 0) return 0; return 1; error: return 0; }
int serval_sign(const char *sid, const size_t sid_len, const unsigned char *msg, const size_t msg_len, char *sig_buffer, const size_t sig_size, const char *keyringName, const size_t keyring_len) { keyring_identity *new_ident; char keyringFile[1024]; assert(msg_len); if (sid) assert(sid_len == 2*SID_SIZE); if (keyringName == NULL || keyring_len == 0) { FORM_SERVAL_INSTANCE_PATH(keyringFile, "serval.keyring"); // if no keyring specified, use default keyring } else { // otherwise, use specified keyring (NOTE: if keyring does not exist, it will be created) strncpy(keyringFile,keyringName,keyring_len); keyringFile[keyring_len] = '\0'; } keyring = keyring_open(keyringFile); keyring_enter_pin(keyring, KEYRING_PIN); // unlocks Serval keyring for using identities (also initializes global default identity my_subscriber) if (!sid) { //create new sid int c; for(c=0;c<keyring->context_count;c++) { // cycle through the keyring contexts until we find one with room for another identity new_ident = keyring_create_identity(keyring,keyring->contexts[c], KEYRING_PIN); // create new Serval identity if (new_ident) break; } if (!new_ident) { fprintf(stderr, "failed to create new SID\n"); return 1; } if (keyring_commit(keyring)) { // need to commit keyring or else new identity won't be saved (needs root permissions) fprintf(stderr, "Failed to save new SID into keyring...make sure you are running as root!\n"); return 1; } sid = alloca_tohex_sid(new_ident->subscriber->sid); // convert SID from binary to hex } else { if (!str_is_subscriber_id(sid)) { fprintf(stderr,"Invalid SID\n"); return 1; } } unsigned char packedSid[SID_SIZE]; stowSid(packedSid,0,sid); unsigned char *key=keyring_find_sas_private(keyring, packedSid, NULL); // get SAS key associated with our SID if (!key) return 1; unsigned char hash[crypto_hash_sha512_BYTES]; unsigned long long sig_length = SIGNATURE_BYTES; crypto_hash_sha512(hash, msg, msg_len); // create sha512 hash of message, which will then be signed unsigned char signed_msg[msg_len + sig_length]; memcpy(signed_msg,msg,msg_len); int ret = crypto_create_signature(key, hash, crypto_hash_sha512_BYTES, &signed_msg[msg_len], &sig_length); // create signature of message hash, append it to end of message if (!ret) { //success printf("%s\n", alloca_tohex(signed_msg + msg_len, sig_length)); printf("%s\n",sid); if (sig_size > 0) { if (sig_size >= 2*sig_length + 1) { strncpy(sig_buffer,alloca_tohex(signed_msg + msg_len,sig_length),2*sig_length); sig_buffer[2*sig_length] = '\0'; } else fprintf(stderr,"Insufficient signature buffer size\n"); } } keyring_free(keyring); return ret; }