int main(void) { unsigned char *alicepk = (unsigned char *) sodium_malloc(crypto_scalarmult_BYTES); unsigned char *bobpk = (unsigned char *) sodium_malloc(crypto_scalarmult_BYTES); unsigned char *k = (unsigned char *) sodium_malloc(crypto_scalarmult_BYTES); int ret; assert(alicepk != NULL && bobpk != NULL && k != NULL); crypto_scalarmult_base(alicepk, alicesk); sodium_bin2hex(hex, sizeof hex, alicepk, crypto_scalarmult_BYTES); printf("%s\n", hex); crypto_scalarmult_base(bobpk, bobsk); sodium_bin2hex(hex, sizeof hex, bobpk, crypto_scalarmult_BYTES); printf("%s\n", hex); ret = crypto_scalarmult(k, alicesk, bobpk); assert(ret == 0); sodium_bin2hex(hex, sizeof hex, k, crypto_scalarmult_BYTES); printf("%s\n", hex); ret = crypto_scalarmult(k, bobsk, alicepk); assert(ret == 0); sodium_bin2hex(hex, sizeof hex, k, crypto_scalarmult_BYTES); printf("%s\n", hex); ret = crypto_scalarmult(k, bobsk, small_order_p); assert(ret == -1); sodium_bin2hex(hex, sizeof hex, k, crypto_scalarmult_BYTES); printf("%s\n", hex); sodium_free(bobpk); sodium_free(alicepk); sodium_free(k); assert(crypto_scalarmult_bytes() > 0U); assert(crypto_scalarmult_scalarbytes() > 0U); assert(strcmp(crypto_scalarmult_primitive(), "curve25519") == 0); assert(crypto_scalarmult_bytes() == crypto_scalarmult_curve25519_bytes()); assert(crypto_scalarmult_scalarbytes() == crypto_scalarmult_curve25519_scalarbytes()); assert(crypto_scalarmult_bytes() == crypto_scalarmult_scalarbytes()); return 0; }
static nif_term_t salt_scalarmult_base(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_scalarmult(Integer) -> Group_q. */ nif_bin_t n; nif_bin_t q; if (argc != 1) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_binary(hp, argv[0], &n)) return (BADARG); /* Check constraints on size. */ if (n.size != crypto_scalarmult_SCALARBYTES) return (BADARG); /* Allocate space for plain text. NB: Passing ENOMEM as BADARG. */ if (! enif_alloc_binary(crypto_scalarmult_BYTES, &q)) return (BADARG); crypto_scalarmult_base(q.data, n.data); return (enif_make_binary(hp, &q)); }
int zmq_curve_public (char *z85_public_key, const char *z85_secret_key) { #if defined (ZMQ_HAVE_CURVE) # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "CURVE encryption library not built correctly" # endif uint8_t public_key[32]; uint8_t secret_key[32]; if (zmq_z85_decode (secret_key, z85_secret_key) == NULL) return -1; // Return codes are suppressed as none of these can actually fail. crypto_scalarmult_base (public_key, secret_key); zmq_z85_encode (z85_public_key, public_key, 32); return 0; #else (void) z85_public_key, (void) z85_secret_key; errno = ENOTSUP; return -1; #endif }
bool unit_test_scalarmult(){ // Random key values uint8_t *random_bytes = malloc(32 * NUM_SCALARMULT * sizeof(uint8_t)); READ_RANDOM_BYTES(32 * NUM_SCALARMULT, random_bytes); // Storage buffers uint8_t expected_bytes[32], hacl_bytes[32]; int a, b; bool pass = true; for (int i = 0; i < NUM_SCALARMULT; i++){ b = tweet_crypto_scalarmult_base(expected_bytes, random_bytes + 32 * i); b =crypto_scalarmult_base(hacl_bytes, random_bytes + 32 * i); a = memcmp(hacl_bytes, expected_bytes, 16 * sizeof (uint8_t)); if (a != 0){ pass = false; printf("Scalarmult base failed\n"); break; } } for (int i = 0; i < NUM_SCALARMULT / 2; i++){ b = tweet_crypto_scalarmult(expected_bytes, random_bytes + 32 * 2 * i, random_bytes + 32 * (2 * i + 1)); b = crypto_scalarmult(hacl_bytes, random_bytes + 32 * 2 * i, random_bytes + 32 * (2 * i + 1)); a = memcmp(hacl_bytes, expected_bytes, 16 * sizeof (uint8_t)); if (a != 0){ pass = false; printf("crypto_scalarmult failed\n"); break; } } free(random_bytes); return pass; }
/** @internal * @brief Starts [email protected] key exchange */ int ssh_client_curve25519_init(ssh_session_t * session){ ssh_string_t * client_pubkey; int rc; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); if (rc < 0) { return SSH_ERROR; } rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1); if (rc == 0){ ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey, session->next_crypto->curve25519_privkey); client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE); if (client_pubkey == NULL) { return SSH_ERROR; } ssh_string_fill(client_pubkey, session->next_crypto->curve25519_client_pubkey, CURVE25519_PUBKEY_SIZE); rc = buffer_add_ssh_string(session->out_buffer,client_pubkey); ssh_string_free(client_pubkey); if (rc < 0) { return SSH_ERROR; } rc = packet_send(session); return rc; }
int crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], unsigned char sk[crypto_kx_SECRETKEYBYTES], const unsigned char seed[crypto_kx_SEEDBYTES]) { crypto_generichash(sk, crypto_kx_SECRETKEYBYTES, seed, crypto_kx_SEEDBYTES, NULL, 0); return crypto_scalarmult_base(pk, sk); }
int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], unsigned char sk[crypto_kx_SECRETKEYBYTES]) { COMPILER_ASSERT(crypto_kx_SECRETKEYBYTES == crypto_scalarmult_SCALARBYTES); COMPILER_ASSERT(crypto_kx_PUBLICKEYBYTES == crypto_scalarmult_BYTES); randombytes_buf(sk, crypto_kx_SECRETKEYBYTES); return crypto_scalarmult_base(pk, sk); }
main() { int i; crypto_scalarmult_base(alicepk,alicesk); for (i = 0;i < 32;++i) { if (alicepk[i] != expectedpk[i]) { fprintf(stderr, "Incorrect byte at position %d: ",i); fprintf(stderr, "expected 0x%x, got 0x%x\n", expectedpk[i], alicepk[i]); exit(1); } } fprintf(stderr, "Test passed.\n"); return 0; }
ClientConfiguration::BackupData ClientConfiguration::fromBackup(QString const& backup, QString const& password) { QByteArray decodedBase32 = Base32::decodeBase32Sequence(backup); if (decodedBase32.size() != BACKUP_DECODED_BYTES) { throw IllegalArgumentException() << "Invalid Backup: Size of decoded Backup String is incorrect (" << decodedBase32.size() << " Bytes instead of " << BACKUP_DECODED_BYTES << " Bytes)."; } unsigned char encryptionKey[BACKUP_ENCRYPTION_KEY_BYTES]; sodium_memzero(encryptionKey, BACKUP_ENCRYPTION_KEY_BYTES); // The pointer to the base32-decoded Backup unsigned char* decodedBase32Ptr = reinterpret_cast<unsigned char*>(decodedBase32.data()); // The Salt used in the PBKDF2 Key Derivation process is embedded in the first 8 bytes of the Backup. QByteArray password8Bit = password.toUtf8(); PKCS5_PBKDF2_HMAC(reinterpret_cast<unsigned char*>(password8Bit.data()), password8Bit.size(), decodedBase32Ptr, BACKUP_SALT_BYTES, BACKUP_KEY_PBKDF_ITERATIONS, BACKUP_ENCRYPTION_KEY_BYTES, encryptionKey); unsigned char nonceBytes[crypto_stream_NONCEBYTES]; sodium_memzero(nonceBytes, crypto_stream_NONCEBYTES); crypto_stream_xor(&decodedBase32Ptr[BACKUP_SALT_BYTES], &decodedBase32Ptr[BACKUP_SALT_BYTES], BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES, nonceBytes, encryptionKey); // The last two bytes of the Backup contain the truncated SHA-256 Hash over the identity and its Private Key. unsigned char controlHash[crypto_hash_sha256_BYTES]; sodium_memzero(controlHash, crypto_hash_sha256_BYTES); crypto_hash_sha256(controlHash, &(decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES); if (sodium_memcmp(&(decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES]), controlHash, BACKUP_HASH_BYTES) != 0) { throw IllegalArgumentException() << "Decryption of Backup failed: Invalid Control Hash (" << controlHash[0] << controlHash[1] << " vs. " << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES] << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + 1] << ")."; } unsigned char derivedPublicKey[PROTO_KEY_LENGTH_BYTES]; crypto_scalarmult_base(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); KeyPair kp = KeyPair::fromArrays(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); QString identityString(QByteArray(reinterpret_cast<char*>(&decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES)); if (!isValidIdentity(identityString)) { throw IllegalArgumentException() << "Invalid ClientConfiguration: Decryption of Backup failed: Not a valid Identity."; } return BackupData(ContactId(identityString.toUtf8()), kp); }
const char *checksum_compute(void) { long long i; long long j; long long tests; for (i = 0;i < mlen;++i) m[i] = i; for (i = 0;i < nlen;++i) n[i] = i + 1; for (i = 0;i < plen;++i) p[i] = i + 2; for (i = 0;i < qlen;++i) q[i] = i + 3; for (i = 0;i < rlen;++i) r[i] = i + 4; for (i = -16;i < 0;++i) p[i] = rand(); for (i = -16;i < 0;++i) n[i] = rand(); for (i = plen;i < plen + 16;++i) p[i] = rand(); for (i = nlen;i < nlen + 16;++i) n[i] = rand(); for (i = -16;i < plen + 16;++i) p2[i] = p[i]; for (i = -16;i < nlen + 16;++i) n2[i] = n[i]; if (crypto_scalarmult_base(p,n) != 0) return "crypto_scalarmult_base returns nonzero"; for (i = -16;i < nlen + 16;++i) if (n2[i] != n[i]) return "crypto_scalarmult_base overwrites input"; for (i = -16;i < 0;++i) if (p2[i] != p[i]) return "crypto_scalarmult_base writes before output"; for (i = plen;i < plen + 16;++i) if (p2[i] != p[i]) return "crypto_scalarmult_base writes after output"; for (tests = 0;tests < 100;++tests) { for (i = -16;i < 0;++i) q[i] = rand(); for (i = -16;i < 0;++i) p[i] = rand(); for (i = -16;i < 0;++i) m[i] = rand(); for (i = qlen;i < qlen + 16;++i) q[i] = rand(); for (i = plen;i < plen + 16;++i) p[i] = rand(); for (i = mlen;i < mlen + 16;++i) m[i] = rand(); for (i = -16;i < qlen + 16;++i) q2[i] = q[i]; for (i = -16;i < plen + 16;++i) p2[i] = p[i]; for (i = -16;i < mlen + 16;++i) m2[i] = m[i]; if (crypto_scalarmult(q,m,p) != 0) return "crypto_scalarmult returns nonzero"; for (i = -16;i < mlen + 16;++i) if (m2[i] != m[i]) return "crypto_scalarmult overwrites n input"; for (i = -16;i < plen + 16;++i) if (p2[i] != p[i]) return "crypto_scalarmult overwrites p input"; for (i = -16;i < 0;++i) if (q2[i] != q[i]) return "crypto_scalarmult writes before output"; for (i = qlen;i < qlen + 16;++i) if (q2[i] != q[i]) return "crypto_scalarmult writes after output"; if (crypto_scalarmult(m2,m2,p) != 0) return "crypto_scalarmult returns nonzero"; for (i = 0;i < qlen;++i) if (q[i] != m2[i]) return "crypto_scalarmult does not handle n overlap"; for (i = 0;i < qlen;++i) m2[i] = m[i]; if (crypto_scalarmult(p2,m2,p2) != 0) return "crypto_scalarmult returns nonzero"; for (i = 0;i < qlen;++i) if (q[i] != p2[i]) return "crypto_scalarmult does not handle p overlap"; if (crypto_scalarmult(r,n,q) != 0) return "crypto_scalarmult returns nonzero"; if (crypto_scalarmult(q,n,p) != 0) return "crypto_scalarmult returns nonzero"; if (crypto_scalarmult(p,m,q) != 0) return "crypto_scalarmult returns nonzero"; for (j = 0;j < plen;++j) if (p[j] != r[j]) return "crypto_scalarmult not associative"; for (j = 0;j < mlen;++j) m[j] ^= q[j % qlen]; for (j = 0;j < nlen;++j) n[j] ^= p[j % plen]; } sodium_bin2hex(checksum, sizeof checksum, p, crypto_scalarmult_BYTES); return 0; }
void doit(void) { crypto_scalarmult(q,n,p); crypto_scalarmult_base(r,n); }
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a * SSH_MSG_KEXDH_REPLY */ int ssh_server_curve25519_init(ssh_session_t * session, ssh_buffer_t * packet){ /* ECDH keys */ ssh_string_t * q_c_string; ssh_string_t * q_s_string; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key_t * privkey; ssh_string_t * sig_blob = NULL; int rc; /* Extract the client pubkey from the init packet */ q_c_string = buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); return SSH_ERROR; } if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){ ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d", (int)ssh_string_len(q_c_string)); ssh_string_free(q_c_string); return SSH_ERROR; } memcpy(session->next_crypto->curve25519_client_pubkey, ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE); ssh_string_free(q_c_string); /* Build server's keypair */ rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1); if (rc == 0){ ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey, session->next_crypto->curve25519_privkey); rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY); if (rc < 0) { ssh_set_error_oom(session); goto error; } /* build k and session_id */ rc = ssh_curve25519_build_k(session); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } /* privkey is not allocated */ rc = ssh_get_key_params(session, &privkey); if (rc == SSH_ERROR) { goto error; } rc = make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto error; } /* add host's public key */ rc = buffer_add_ssh_string(session->out_buffer, session->next_crypto->server_pubkey); if (rc < 0) { ssh_set_error_oom(session); goto error; } /* add ecdh public key */ q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE); if (q_s_string == NULL) { goto error; } ssh_string_fill(q_s_string, session->next_crypto->curve25519_server_pubkey, CURVE25519_PUBKEY_SIZE); rc = buffer_add_ssh_string(session->out_buffer, q_s_string); ssh_string_free(q_s_string); if (rc < 0) { ssh_set_error_oom(session); goto error; } /* add signature blob */ sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); goto error; } rc = buffer_add_ssh_string(session->out_buffer, sig_blob); ssh_string_free(sig_blob); if (rc < 0) { ssh_set_error_oom(session); goto error; } SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent"); rc = packet_send(session); if (rc == SSH_ERROR) { return SSH_ERROR; } /* Send the MSG_NEWKEYS */ rc = buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); if (rc < 0) { goto error; } session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; rc = packet_send(session); SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return rc; error: buffer_reinit(session->out_buffer); return SSH_ERROR; }