// PureNoise CryptoLib (c) 1997-2004, PureNoise Ltd Vaduz // Ruptor's ECDH sample code (unchecked, may contain errors, may not compile) #include "crypto.h" #include "chaos/chaos.h" #include "aes/aes.h" #include "channel/channel.h" int sample_ecdh (aes_keystream *incoming_ks, aes_keystream *outgoing_ks) // incoming traffic decryption and outgoing traffic encryption key streams { // Important Note: // keep them all ECC_WORDS + 3: + 1 for size + 1 for trailing zero + 1 to protect from overflow caused by big_psub <- big_redc <- nres_modmult <- nres_powmod <- nres_sqroot <- ecc_point_set unsigned long local_sec[ECC_WORDS + 3]; // Local Secret Key (just a random number) ecc_point local_epub; // Local Public Key = ECC_XYZ * (Local Secret Key) in N-RESIDUE format - X includes LSB of redc(Y) in X[ECC_WORDS+1] ecc_point remote_epub; // Remote Public Key = ECC_XYZ * (Remote Secret Key) in N-RESIDUE format - X includes LSB of redc(Y) in X[ECC_WORDS+1] ecc_point ecommon; // Common Key = ECC_XYZ * (Local/Remote Secret Key) * (Remote/Local Public Key) in N-RESIDUE format - no need to convert, just use it like that: who cares? unsigned long y[ECC_WORDS + 3], i; // Y coordinate in binary form (converted back from n-residue) - a bs temporary variable channel_new_keypair (local_sec, &local_epub); // generates a new random keypair ... if (x = send_key (local_epub.X)) return x; // transmission errors ... if (x = recv_key (remote_epub.X)) return x; // transmission or traffic decryption errors if (remote_epub.X[0] < ECC_WORDS - 1) return -1; // ERROR_PUBLIC_KEY_TOO_SHORT: any shorter is unacceptable ... ecc_point_mult (local_sec, remote_epub, &ecommon); // it also resets the sign of the Y coordinate to 0, which is handy ecc_point_norm (ecommon); // EPOINT_NORMALIZED to make sure they always match if (ecommon.X[0] < ECC_WORDS - 1) return -1; // ERROR_PUBLIC_KEY_TOO_SHORT: any shorter is unacceptable if (ecommon.X[0] < ECC_WORDS) ecommon.X[++(ecommon.X[0])] = 0; // making sure that public key X coordinate is exactly ECC_WORDS long (one 0 is acceptable) ... memset (y, 'R', CIPHER_KEY_BYTES); chaos_block (y, CIPHER_KEY_WORDS, remote_epub.X, (ECC_WORDS+3)*2); // compressing both coordinates into one 256-bit block - better than standard hashes chaos_block (y, CIPHER_KEY_WORDS, ecommon.X, (ECC_WORDS+3)*2); // compressing both coordinates into one 256-bit block - better than standard hashes aes_setkey (y, incoming_ks); // decrypt incoming traffic with this key stream memset (y, 'R', CIPHER_KEY_BYTES); chaos_block (y, CIPHER_KEY_WORDS, local_epub.X, (ECC_WORDS+3)*2); // compressing both coordinates into one 256-bit block - better than standard hashes chaos_block (y, CIPHER_KEY_WORDS, ecommon.X, (ECC_WORDS+3)*2); // compressing both coordinates into one 256-bit block - better than standard hashes aes_setkey (y, outgoing_ks); // encrypt outgoing traffic with this key stream // keys and coordinates can be destroyed now return 0; // Remember, it's just an example! // Use authenticated Kim-Song key exchange instead of standard Diffie-Hellman // Check keys validity before exchanging traffic // On the first exchange always verify the common key fingerprint outside the protocol // Good luck! Stay secure. Stay out of trouble. // Ruptor }