Security

Cyber Security - Encryption Key Exchanges

Illustrated by Sergey Konotopcev

Overview

Encryption of data, both at rest in databases and while in transit, ensures both security and privacy, and with that goes the need to protect private encryption keys. The RSA Asymmetric encryption method uses a freely available public key to encrypt data, which is then decrypted with a mathematically linked private key.

Hashing functions check message validity by irreversibly encrypting data of any length to a fixed length hash value. The receiver of the file or message then calculates the hash value with the agreed-to method, such as SHA-256, and compares that value to the known, public hash value. But asymmetric encryption is much slower than symmetric encryption, which uses the same key to encrypt and decrypt messages. And both encryption methods require secure exchange of encryption keys between the parties.

The Diffie-Hellman encryption key exchanges discussed here avoid actually sending encryption keys between parties. The keys are computed mathematically from actual values exchanged, and these values alone are insufficient for eavesdroppers to derive keys.

Human factors cause most security breaches, by users answering phishing emails or downloading malware from compromised websites or fake sites posing as the real thing. The best security is useless if you've been hacked and maybe keystroke loggers or screen scrapers have compromised your computer. But antivirus software helps to protect against this. Virtual private networks (VPNs) can also be used so that messages are encrypted and can't be traced back to specific computers. VPNs mitigate the effects of man-in-the-middle (MITM) attacks where crooks hijack data exchanges to monitor and modify content.

Bad actors pretend to be the sender to the recipient, and the recipient to the sender. But running browsers in virtual machines can limit damage in the event of a successful hack by an intruder.

The W3C released a web cryptographic API in 2017, complete with JavaScript examples. And other JavaScript security libraries include the Stanford JavaScript Cryptographic Library—SJCL—which is discussed here.

In the past, transmission security has been achieved with Secure Sockets Layer (SSL) software running on top of the TCP/IP protocol used to transport and route data over networks. Sensitive data was encrypted with the symmetric-key algorithm Data Encryption Standard (DES), but this "HTTPS" protocol using SSL over HTTP is no longer secure. SSL has been deprecated by the Internet Engineering Task Force (IETF) and replaced with Transport Layer Security, TLS. By the late 1990s, DES was also no longer secure, so a competition was held by the National Institute of Standards and Technology (NIST) to find a replacement. As a result, the Rijndael symmetric-block cipher algorithm was chosen as the new Advanced Encryption Standard (AES).

Protecting Data Transmission

Computer security includes using secure hardware-based logins with technologies like iris or fingerprint scanning. And multimode authentication is also used, where extra information is requested to confirm users' identities once a user name and password are successfully entered.This can include asking security questions, such as a user's mother's maiden name—but that particular piece of information is readily available and is NOT secure! Or a temporary PIN (personal identification number) may be sent to users via a phone call, text message, or email, and then the PIN is entered at the website.

Use of the HTTP Secure (HTTPS) protocol on the internet helps to protect data, but web pages called via HTTPS cease to be secure if they access regular HTTP pages. And operating systems and browsers must be properly configured to use the most secure transmission methods, with SSL disabled and TLS enabled.

This article focuses on encryption key exchanges rather than human factors. But don't write your password at work on a sticky note and paste it to your computer screen—you don't know who the office cleaners might be working for!

There are several requirements at the core of secure data transactions:

  1. Confidentiality—Encrypt text to make it unreadable.
  2. Integrity—Ensure text is tamper-proof: use a message authentication code (MAC).
  3. Authentication and Non-repudiation—Content comes from trusted sources
    \t and the sender really sent the message
    by using a hashed MAC—HMAC.
  4. Perfect Forward Secrecy—Avoid future compromise with temporary, ephemeral encryption keys.
  5. Availability—Ensure timely and reliable access to
    client-side JavaScript code employing the SJCL library in web pages, such as a login page, may look something like the following pseudocode:

From sender - sjcl.encrypt('secretSharedKey','plainTextToEncrypt')
AND
To receiver - sjcl.decrypt('secretSharedKey', 'cipherTextToDecrypt')

Both senders and receivers must securely store the "secretShared Key", which must not be the same as users' passwords. Zero-knowledge methods, such as Elliptical Curve Diffie-Hellman (ECDH), are used to exchange secret values, where the actual encryption key chosen from a point on an elliptical curve isn't transmitted between sender and receiver.

In the more general case, a TLS secure communications session between a sender and receiver, or client and server, might proceed as follows:

  • Client opens session and checks server's identity, e.g., X.509 public key certificate.
  • Server checks client's identity.
  • Establish most secure mutually supported encryption suite from lists on server and client.
  • Exchange asymmetrically encoded cryptographic set-up information encoded with server's public key, including set-up information for temporary, ephemeral symmetric encryption.
  • Switch to symmetric encryption on completion of asymmetrically encrypted set-up information exchange, and then send the symmetrically encrypted message body.
  • After message is sent, discard ephemeral keys and close session.
  • Server checks integrity and decrypts message.

AES uses the Rijndael symmetric-block cipher algorithm with key lengths of 128, 192, or 256 bits, and fixed data block sizes of 128 bits for both input and output text blocks. Elliptical curve cryptography (ECC) uses points on elliptical curves to compute shorter, more secure keys than RSA, with a 512-bit ECC key being as hard to crack as a 15,360-bit RSA key.

Diffie-Hellman Key Exchange

The Diffie-Hellman key exchange method was made significantly more secure by using elliptical curves instead of pseudo-random number generators. With Elliptical Curve Diffie-Hellman (ECDH), two parties each use different secret random numbers (private keys), x and y, and each party transmits the value of the public key (P) raised to the power of the private key, x or y. So the publicly revealed data is limited to the values of Px and Py.

The sender generates a random pre-master secret key, encrypts it with a receiver's public key, and then sends it to the receiver. The receiver uses their private key for decryption, and creates the shared master-secret.

The client-side set-up code for Diffie-Hellman follows:

// Most of this Javascript code was written by Tom Wu at Stanford U.

<script language="JavaScript" type="text/javascript" src="tomWu_files/jsbn0000.js">
// Above file contains Big Number math functions </script>
<script language="JavaScript" type="text/javascript" src="tomWu_files/jsbn2000.js">
// Above file contains extended Big Number math functions </script>
<script language="JavaScript" type="text/javascript" src="tomWu_files/prng4000.js">
// Above file contains Pseudo Random Number Generator </script>
<script language="JavaScript" type="text/javascript" src="tomWu_files/rng00000.js">
// Above file contains Random Number Generator.  Requires the prng file prng4000.js
</script>
<script language="JavaScript" type="text/javascript" src="tomWu_files/ec000000.js">
// Above file contains Javascript Elliptic Curve implementation </script>
<script language="JavaScript" type="text/javascript" src="tomWu_files/sec00000.js">
// Above file contains Elliprical Curves such as secp192r1 used below </script>

<script language="JavaScript">
<!--

var name;

function set_ec_params(name) {
  var c = getSECCurveByName(name);
  document.ecdhtest.q.value = c.getCurve().getQ().toString();
  document.ecdhtest.a.value = c.getCurve().getA().toBigInteger().toString();
  document.ecdhtest.b.value = c.getCurve().getB().toBigInteger().toString();
  document.ecdhtest.gx.value = c.getG().getX().toBigInteger().toString();
  document.ecdhtest.gy.value = c.getG().getY().toBigInteger().toString();
  document.ecdhtest.n.value = c.getN().toString();
  document.ecdhtest.alice_priv.value = "";
  document.ecdhtest.alice_pub_x.value = "";
  document.ecdhtest.alice_pub_y.value = "";
  document.ecdhtest.alice_key_x.value = "";
  document.ecdhtest.alice_key_y.value = "";
}

function set_secp192r1() {
  if (name == "") set_ec_params("secp192r1");
  else\t\t\t\t\t\t\t// OnLoad default curve. Code
  {\t\t\t\t\t\t\t// for 128, 160, 224, and 256 
    name = "";\t\t\t\t\t\t// curves has been removed
    set_ec_params("secp192r1");
    rng = new SecureRandom();
    do_alice_rand();
  }
}

One party knows x and the value of Py and the other knows y and the value of Px, so both parties can calculate the shared key, P(xy), as both (Py)x = P(xy) and (Px)y = P(x*y). As long as x and y stay secret, eavesdroppers can only discover the transmitted values, Px and Py, but not the shared key.

If both x and y are ephemeral, the shared key is as well. In the next image, "Alice" is the sender and "twECDHserver.html" is the receiver's web page.

var rng;

function do_init(nameToUse) {
  if(document.ecdhtest.q.value.length == 0) set_secp192r1(); // set_secp192r1();
  rng = new SecureRandom();
  do_alice_rand();
}

function get_curve() {
  return new ECCurveFp(new BigInteger(document.ecdhtest.q.value),
    new BigInteger(document.ecdhtest.a.value),
    new BigInteger(document.ecdhtest.b.value));
}

function get_G(curve) {
  return new ECPointFp(curve,
    curve.fromBigInteger(new BigInteger(document.ecdhtest.gx.value)),
    curve.fromBigInteger(new BigInteger(document.ecdhtest.gy.value)));
}

function pick_rand() {
  var n = new BigInteger(document.ecdhtest.n.value);
  var n1 = n.subtract(BigInteger.ONE);
  var r = new BigInteger(n.bitLength(), rng);
  return r.mod(n1).add(BigInteger.ONE);
}

function do_alice_rand() {
  var r = pick_rand();
  document.ecdhtest.alice_priv.value = r.toString();
  document.ecdhtest.alice_pub_x.value = "";
  document.ecdhtest.alice_pub_y.value = "";
  document.ecdhtest.alice_key_x.value = "";
  document.ecdhtest.alice_key_y.value = "";
  do_alice_pub();
}

function do_alice_pub() {
  var before = new Date();
  var curve = get_curve();
  var G = get_G(curve);
  var a = new BigInteger(document.ecdhtest.alice_priv.value);
  var P = G.multiply(a);
  var after = new Date();
  alicePubX = P.getX().toBigInteger().toString();
  alicePubY = P.getY().toBigInteger().toString();
  document.ecdhtest.alice_pub_x.value = alicePubX;
  document.ecdhtest.alice_pub_y.value = alicePubY;
  document.getElementById("ecdhServer").src = "twECDHServer.html?X="+
\t\t\t\t\t\t\t\talicePubX+
\t\t\t\t\t\t\t\t"&Y="+alicePubY+
\t\t\t\t\t\t\t\t"&curve="+name;
}

Alice's values are sent to Bob, the receiver/server, in the last line of this code. The concatenated value is strengthened (stretched) by repeatedly hashing thousands of times with Password-Based Key Derivation Function 2 (PBKDF2) methods.

Since password strengthening slows calculations, a range of 500 to 2500 produces acceptable results with minimal delays. SJCL uses thousands of repeated hashes to make brute force attacks harder and the pattern used is : Hash(Salt | Hash(UserName | ":" | Password)), so the concatenated "Salt","UserName", ":", and "Password" might look something like this: "9+Va5voDXA=JohnSmith:k473#bGu!Oo6*27\\Y1n0a9c~".

The colon ( : ) between User Name and Password makes each pair unique, and avoids hashing user name "timSmith" and password "oldman", the same as "timSmit" and "holdman". With no ":", the string for both is timSmitholdman, vs timeSmith:oldman and timSmit:holdman with a ":".

Two parties using Diffie-Hellman agree on a large prime number, "N", and a smaller number "g" that's primitive with respect to N. g being primitive to N means that integers, "k", can be found where ( k = gi mod N ) for all the values of i from 1 to N-1. So g is primitive to N if all of the individual values of k are also equal to all the integers from 1 to N-1.

Hash functions are one-way, so it's extremely difficult to derive the original string from the hash. To ensure validity that it hasn't been tampered with, and that it comes from a trusted source, a known and expected hash value for encrypted text is compared to a newly computed hash value.

The English language has about 100,000 words, so to brute force crack a hashed password up to 100,000 attempts might be needed. By adding a 32-bit salt to the password, the number of possible passwords are:

Password Possibilities \t = 100,000
Salt Possibilities\t\t = 232 ( 32-bit )
Hash calculations required = Password Possibilities * Salt Possibilities
Hash calculations required = 100,000 * 232
Hash calculations required = 429,496,729,600,000

Seeded/salted strings are strengthened in this way to resist attacks that use precomputed "Rainbow" tables to crack cryptographic hash functions.

With CBC (cipher block chaining) encryption, whole blocks of text of the specified length are encoded, and each encoded text block depends on the previous source blocks. If needed the last block is padded to make it the required fixed block length, and as there is no data before the first block, messages are encoded with a unique, random initialization vector (IV).

Note that compression must NOT be used. It makes text vulnerable to hacking by replacing repeating character strings with smaller tokens.

In ECDH, elliptical curve points provide the public and private encryption keys, and predefined values include N and g for an agreed-to curve. Both parties create private and public keys, exchange public keys, and multiply their private key by the other's public key to derive the shared secret key—see the following code:

function get_bob_pub()
{
  var ifrm = document.getElementById("ecdhServer");
  document.ecdhtest.bob_pub_x.value = ifrm.contentWindow.bobPubX;
  document.ecdhtest.bob_pub_y.value = ifrm.contentWindow.bobPubY;
  var before = new Date();
  var curve = get_curve();
  var alicePubX = document.ecdhtest.alice_pub_x.value;
  var alicePubY = document.ecdhtest.alice_pub_y.value;
  var P = new ECPointFp(curve,
    curve.fromBigInteger(new BigInteger(document.ecdhtest.bob_pub_x.value)),
    curve.fromBigInteger(new BigInteger(document.ecdhtest.bob_pub_y.value)));
  var a = new BigInteger(document.ecdhtest.alice_priv.value);
  var S = P.multiply(a);
  var after = new Date();
  document.ecdhtest.alice_key_x.value = S.getX().toBigInteger().toString();
  document.ecdhtest.alice_key_y.value = S.getY().toBigInteger().toString();
  if (name == "") name = "secp192r1";
}
//-->
</script>
  </head>
  <body onload="do_init();">

The foregoing code gets Bob's values and computes Alice's shared secret key. With compact representation, the x-coordinate of the derived point on the curve is the shared secret, and authentication data ("adata") can also be added. The encoded text block returned might look like this:

{
  "iv":"HV9Xro6SvCgq17ReXAsn4Q==",
  "v":1,
  "iter":1000,
  "ks":256,
  "ts":128,
  "mode":"ccm",
  "adata":"authorization&nbsp;data",
  "cipher":"aes",
  "salt":"ObpiMz7YLFw=",
  "ct":"p5/DJ8yRQPHOrnEUu6d4o1Q9JTKSNzrWgy8KO6MGIDy"
}

The initialization Vector is "iv", version number is "v", "iter" is a password-strengthening factor, key size in bits is "ks", authentication tag size in bits is "ts", "mode" is the cipher mode, "adata" is the authentication data string—can be a timestamp to limit multiple login tries. The algorithm used for encryption is "cipher", "salt" is the password Salt, and "ct" is the encrypted ciphertext that's sent between the two parties exchanging messages.

Conclusion

Using Elliptical Curve Diffie-Hellman (ECDH) to exchange encryption keys provides greatly improved key security. Combined with 256-bit AES encryption of message content, much greater security is achieved than was possible in the past.
At http://web2ria.com/#95, and http://bitwiseshiftleft.github.io/sjcl/demo/ are the two ECDH examples (key exchange and the full encryption demo). See https://www.garykessler.net/library/crypto.html#dhmath for a longer article. The example pages at Web2RIA and Github use client-side data exchanges, but both PHP and C# server-side languages have Diffie-Hellman functions, and AJAX can be used for browser-server data exchanges.

Phil Pearl

author

After a successful career in the oil-field service business all over the World in field and management positions, I transitioned to computer software, and in 2000 I decided to focus exclusively on designing and coding web pages and sites. As the web software industry became increasingly specialized, I shifted from full-stack design and development to working on front-end, browser-based code.

When the Internet industry began to favor large code libraries, I concentrated on writing efficient hand-coded software for web sites and pages for companies such as Microsoft, Wells Fargo bank, and Intermountain Health Care ( IHC ), and government departments like the Bureau of Land Managmenet ( BLM ). Along the way I also wote software for the FBI to conduct an undercover sting operation.

My work for Microsoft Research took me into the Cyber Security area, and I updated the book that I wrote on developing Web 2.0 Rich Internet Applications ( RIAs ), with a new chapter on Cyber Security. As well as that book, I've written several articles for various web sites, and published a number of books on Amazon. These include two novels, the second of which is titled "Cyber Insecurity", as well as a childrens' book.

I'm currently working on finshing my second children's book.

Sergey Konotopcev

illustrator