Key Encapsulation Mechanism

[Wikipedia] Key encapsulation mechanisms (KEMs) are a class of encryption techniques designed to secure symmetric cryptographic key material for transmission using asymmetric (public-key) algorithms. In practice, public key systems are clumsy to use in transmitting long messages. Instead they are often used to exchange symmetric keys, which are relatively short. The symmetric key is then used to encrypt the longer message. The traditional approach to sending a symmetric key with public key systems is to first generate a random symmetric key and then encrypt it using the chosen public key algorithm. The recipient then decrypts the public key message to recover the symmetric key. As the symmetric key is generally short, padding is required for full security and proofs of security for padding schemes are often less than complete. KEMs simplify the process by generating a random element in the finite group underlying the public key system and deriving the symmetric key by hashing that element, eliminating the need for padding.

JPBC provides a support class called KEMCipher which simplifies the integration of a KEM and a Cipher. The following is an example of how to use the class.

Usage


1    package it.unisa.dia.gas.crypto.kem;
2    
3    import it.unisa.dia.gas.crypto.circuit.Circuit;
4    import it.unisa.dia.gas.crypto.circuit.DefaultCircuit;
5    import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.engines.GGHSW13KEMEngine;
6    import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.GGHSW13KeyPairGenerator;
7    import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.GGHSW13ParametersGenerator;
8    import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.GGHSW13SecretKeyGenerator;
9    import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.params.*;
10   import it.unisa.dia.gas.crypto.kem.cipher.engines.KEMCipher;
11   import it.unisa.dia.gas.crypto.kem.cipher.params.KEMCipherDecryptionParameters;
12   import it.unisa.dia.gas.crypto.kem.cipher.params.KEMCipherEncryptionParameters;
13   import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
14   import it.unisa.dia.gas.plaf.jpbc.util.concurrent.ExecutorServiceUtils;
15   import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
16   import org.bouncycastle.crypto.CipherParameters;
17   import org.bouncycastle.jce.provider.BouncyCastleProvider;
18   
19   import javax.crypto.Cipher;
20   import javax.crypto.spec.IvParameterSpec;
21   import java.security.GeneralSecurityException;
22   import java.security.SecureRandom;
23   import java.security.Security;
24   import java.security.spec.AlgorithmParameterSpec;
25   
26   import static it.unisa.dia.gas.crypto.circuit.Circuit.Gate.Type.*;
27   import static org.junit.Assert.assertEquals;
28   
29   
30   /**
31    * @author Angelo De Caro (jpbclib@gmail.com)
32    */
33   public class KEMCipherGGHSW13KEM {
34       protected KEMCipher kemCipher;
35       protected AlgorithmParameterSpec iv;
36   
37       protected AsymmetricCipherKeyPair keyPair;
38   
39   
40       public KEMCipherGGHSW13KEM() throws GeneralSecurityException {
41           this.kemCipher = new KEMCipher(
42                   Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"),
43                   new GGHSW13KEMEngine()
44           );
45   
46           // build the initialization vector.  This example is all zeros, but it
47           // could be any value or generated using a random number generator.
48           iv = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
49       }
50   
51   
52       public AsymmetricCipherKeyPair setup(int n) {
53           GGHSW13KeyPairGenerator setup = new GGHSW13KeyPairGenerator();
54           setup.init(new GGHSW13KeyPairGenerationParameters(
55                   new SecureRandom(),
56                   new GGHSW13ParametersGenerator().init(
57                           PairingFactory.getPairing("params/mm/ctl13/toy.properties"),
58                           n).generateParameters()
59           ));
60   
61           return (keyPair = setup.generateKeyPair());
62       }
63   
64   
65       public byte[] initEncryption(String assignment) {
66           try {
67               return kemCipher.init(
68                       true,
69                       new KEMCipherEncryptionParameters(
70                               128,
71                               new GGHSW13EncryptionParameters(
72                                       (GGHSW13PublicKeyParameters) keyPair.getPublic(),
73                                       assignment
74                               )
75                       ),
76                       iv
77               );
78           } catch (Exception e) {
79               throw new RuntimeException(e);
80           }
81       }
82   
83       public byte[] encrypt(String message) {
84           try {
85               return kemCipher.doFinal(message.getBytes());
86           } catch (Exception e) {
87               throw new RuntimeException(e);
88           }
89       }
90   
91   
92       public CipherParameters keyGen(Circuit circuit) {
93           GGHSW13SecretKeyGenerator keyGen = new GGHSW13SecretKeyGenerator();
94           keyGen.init(new GGHSW13SecretKeyGenerationParameters(
95                   (GGHSW13PublicKeyParameters) keyPair.getPublic(),
96                   (GGHSW13MasterSecretKeyParameters) keyPair.getPrivate(),
97                   circuit
98           ));
99   
100          return keyGen.generateKey();
101      }
102  
103      public byte[] decrypt(CipherParameters secretKey, byte[] encapsulation, byte[] ciphertext) {
104          try {
105              kemCipher.init(
106                      false,
107                      new KEMCipherDecryptionParameters(secretKey, encapsulation, 128),
108                      iv
109              );
110              return kemCipher.doFinal(ciphertext);
111          } catch (Exception e) {
112              throw new RuntimeException(e);
113          }
114      }
115  
116  
117  
118      public static void main(String[] args) {
119          Security.addProvider(new BouncyCastleProvider());
120  
121          try {
122              // Setup
123              int n = 4;
124              KEMCipherGGHSW13KEM engine = new KEMCipherGGHSW13KEM();
125              engine.setup(n);
126  
127              // Encrypt
128              String message = "Hello World!!!";
129              byte[] encapsulation = engine.initEncryption("1101");
130              byte[] ciphertext = engine.encrypt(message);
131  
132              // Decrypt
133              int q = 3;
134              Circuit circuit = new DefaultCircuit(n, q, 3, new DefaultCircuit.DefaultGate[]{
135                      new DefaultCircuit.DefaultGate(INPUT, 0, 1),
136                      new DefaultCircuit.DefaultGate(INPUT, 1, 1),
137                      new DefaultCircuit.DefaultGate(INPUT, 2, 1),
138                      new DefaultCircuit.DefaultGate(INPUT, 3, 1),
139  
140                      new DefaultCircuit.DefaultGate(AND, 4, 2, new int[]{0, 1}),
141                      new DefaultCircuit.DefaultGate(OR, 5, 2, new int[]{2, 3}),
142  
143                      new DefaultCircuit.DefaultGate(AND, 6, 3, new int[]{4, 5}),
144              });
145              byte[] plaintext = engine.decrypt(engine.keyGen(circuit), encapsulation, ciphertext);
146  
147              assertEquals(true, message.equals(new String(plaintext)));
148          } catch (Exception e) {
149              e.printStackTrace();
150          } finally {
151              ExecutorServiceUtils.shutdown();
152          }
153      }
154  
155  }