Integrated Encryption Scheme (IES) - Elliptic Curve[ECIES Home][Home]
Integrated Encryption Scheme (IES) is a hybrid encryption scheme which allows Alice to get Bob's public key, and then generate an encryption key based on this public key and her private key. Initially Bob and Alice agree on an elliptic curve with a base point (\(G\)), an order (\(n\)) and a prime number (\(p\)). If Bob has a private key of \(b\), he can share his public key of \(B=bG\). Alice receives this public key, and generates a private key (\(a\)). Alice then computes \(Key=aB\) and which is \(Key=abG\). She will then take a message (\(m\)) and encrypt with this key, and send to Bob with her public key (\(A=aG\)). Bob can then construct this key with \(Key=bA\), and can then decrypt the message [Hybrid (Discrete logs)][Hybrid (Elliptic Curve)].
|
Theory
Integrated Encryption Scheme (IES) is a hybrid encryption scheme which allows Alice to get Bob's public key, and then generate an encryption key based on this public key and her private key. Initially Bob and Alice agree on an elliptic curve with a base point (\(G\)), an order (\(n\)) and a prime number (\(p\)). If Bob has a private key of \(b\), he can share his public key of
\(B=bG\)
Alice receives this public key, and generates a private key (\(a\)). Alice then computes:
\(Key=bA\)
and which is:
\(Key=abG\)
She will then take a message (\(m\)) and encrypt with this key, and send to Bob with her public key:
\(A=bG\)
Bob can then construct this key with:
\(Key=KDF(bA)\)
and can then decrypt the message. In the following example we use PBKDF2 as the Key Derivation Function (KDF).
Coding
The following is the code:
from secp256k1 import curve,scalar_mult,is_on_curve import random import sys from Crypto.Hash import SHA256 from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Protocol.KDF import PBKDF2 import Padding import binascii def encrypt(plaintext,key, mode): encobj = AES.new(key,mode) return(encobj.encrypt(plaintext)) def decrypt(ciphertext,key, mode): encobj = AES.new(key,mode) return(encobj.decrypt(ciphertext)) print("Basepoint:\t", curve.g) msg="Hello12" if (len(sys.argv)>1): msg=(sys.argv[1]) a = random.randrange(1, curve.n) b = random.randrange(1, curve.n) A = scalar_mult(a,curve.g) B= scalar_mult(b,curve.g) K1= scalar_mult(a,B) print ("Message: ",msg) print ("\na (Alice):\t",a) print ("b (Bob):\t",b) print ("\nA (Alice) aG:\t",A) print ("B (Bob) bG:\t",B) salt = get_random_bytes(16) key = PBKDF2(str(K1[0]), salt, 32, count=1000, hmac_hash_module=SHA256) plaintext = Padding.appendPadding(msg,blocksize=Padding.AES_blocksize,mode=0) ciphertext = encrypt(plaintext.encode(),key,AES.MODE_ECB) print ("\nKey: KDF(abG) ",binascii.hexlify(bytearray(key)).decode()) print ("Ciphertext: ",binascii.hexlify(bytearray(ciphertext)).decode()) plaintext = decrypt(ciphertext,key,AES.MODE_ECB) plaintext = Padding.removePadding(plaintext.decode(),mode=0) print ("\nBob computes plaintext: ",plaintext)
And a sample run:
Basepoint: (55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424) Message: Buzz Lightyear a (Alice): 40979724007234306723700858798671990712800660819077943610005341565220696004702 b (Bob): 19083761352740274642098894747370491425661480826886682521773091829562624498116 A (Alice) aG: (7280348578124714486783960932049032669908641450989528081168193504163245402981, 13680724886278489609349717858347319621071299939224593447568792992941017817164) B (Bob) bG: (10092239408946548870449312112249181646672301560401695092883288951297934400850, 105510569139779171061042697129294179159643291210029455380160616726616896378520) Key: KDF(abG) eb323a6f8660775814f900af1826fab2f3ce1a22b41a7d7eeacc3223a1c1a1aa Ciphertext: bf2d9636a28aef3a08f23f9c2263aa57 Bob computes plaintext: Buzz Lightyear