Fully Secure Functional Encryption: Attribute-Based Encryption and (Hierarchical) Inner Product Encryption

Authors

Allison Lewko and Tatsuaki Okamoto and Amit Sahai and Katsuyuki Takashima and Brent Waters

Abstract

In this paper, we present two fully secure functional encryption schemes. Our first result is a fully secure attribute-based encryption (ABE) scheme. Previous constructions of ABE were only proven to be selectively secure. We achieve full security by adapting the dual system encryption methodology recently introduced by Waters and previously leveraged to obtain fully secure IBE and HIBE systems. The primary challenge in applying dual system encryption to ABE is the richer structure of keys and ciphertexts. In an IBE or HIBE system, keys and ciphertexts are both associated with the same type of simple object: identities. In an ABE system, keys and ciphertexts are associated with more complex objects: attributes and access formulas. We use a novel information-theoretic argument to adapt the dual system encryption methodology to the more complicated structure of ABE systems. We construct our system in composite order bilinear groups, where the order is a product of three primes. We prove the security of our system from three static assumptions. Our ABE scheme supports arbitrary monotone access formulas. Our second result is a fully secure (attribute-hiding) predicate encryption (PE) scheme for inner-product predicates. As for ABE, previous constructions of such schemes were only proven to be selectively secure. Security is proven under a non-interactive assumption whose size does not depend on the number of queries. The scheme is comparably efficient to existing selectively secure schemes. We also present a fully secure hierarchical PE scheme under the same assumption. The key technique used to obtain these results is an elaborate combination of the dual system encryption methodology (adapted to the structure of inner product PE systems) and a new approach on bilinear pairings using the notion of dual pairing vector spaces (DPVS) proposed by Okamoto and Takashima.

Usage


1    package it.unisa.dia.gas.crypto.arcanum.fe.ip.lostw10;
2    
3    import it.unisa.dia.gas.crypto.fe.PredicateOnlyEncryptionScheme;
4    import it.unisa.dia.gas.crypto.arcanum.fe.ip.lostw10.engines.IPLOSTW10PredicateOnlyEngine;
5    import it.unisa.dia.gas.crypto.arcanum.fe.ip.lostw10.generators.IPLOSTW10KeyPairGenerator;
6    import it.unisa.dia.gas.crypto.arcanum.fe.ip.lostw10.generators.IPLOSTW10ParametersGenerator;
7    import it.unisa.dia.gas.crypto.arcanum.fe.ip.lostw10.generators.IPLOSTW10SecretKeyGenerator;
8    import it.unisa.dia.gas.crypto.arcanum.fe.ip.lostw10.params.*;
9    import Element;
10   import Pairing;
11   import PairingFactory;
12   import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
13   import org.bouncycastle.crypto.CipherParameters;
14   import org.bouncycastle.crypto.InvalidCipherTextException;
15   
16   import java.security.SecureRandom;
17   import java.util.Random;
18   
19   import static org.junit.Assert.assertEquals;
20   
21   /**
22    * @author Angelo De Caro (arcanumlib@gmail.com)
23    */
24   public class IPLOSTW10 {
25   
26   
27       public IPLOSTW10() {
28       }
29   
30   
31       public AsymmetricCipherKeyPair setup(int n) {
32           IPLOSTW10KeyPairGenerator setup = new IPLOSTW10KeyPairGenerator();
33           setup.init(new IPLOSTW10KeyGenerationParameters(
34                   new SecureRandom(),
35                   createParameters(n)
36           ));
37   
38           return setup.generateKeyPair();
39       }
40   
41       public IPLOSTW10Parameters createParameters(int n) {
42           return new IPLOSTW10ParametersGenerator().init(
43                   PairingFactory.getPairingParameters("params/curves/a.properties"),
44                   n).generateParameters();
45       }
46   
47       public byte[] encrypt(CipherParameters publicKey, Element[] x) {
48           try {
49               PredicateOnlyEncryptionScheme engine = new IPLOSTW10PredicateOnlyEngine();
50               engine.init(true, new IPLOSTW10EncryptionParameters((IPLOSTW10PublicKeyParameters) publicKey, x));
51   
52               return engine.process();
53           } catch (InvalidCipherTextException e) {
54               throw new RuntimeException(e);
55           }
56       }
57   
58       public CipherParameters keyGen(CipherParameters privateKey, Element[] y) {
59           IPLOSTW10SecretKeyGenerator keyGen = new IPLOSTW10SecretKeyGenerator();
60           keyGen.init(new IPLOSTW10SecretKeyGenerationParameters(
61                   (IPLOSTW10MasterSecretKeyParameters) privateKey,
62                   y
63           ));
64   
65           return keyGen.generateKey();
66       }
67   
68       public boolean test(CipherParameters secretKey, byte[] ciphertext) {
69           try {
70               PredicateOnlyEncryptionScheme engine = new IPLOSTW10PredicateOnlyEngine();
71               engine.init(false, secretKey);
72   
73               return engine.evaluate(ciphertext);
74           } catch (InvalidCipherTextException e) {
75               throw new RuntimeException(e);
76           }
77       }
78   
79   
80       public Element[][] createOrthogonalVectors(CipherParameters publicKey, int n) {
81           Pairing pairing = PairingFactory.getPairing(((IPLOSTW10PublicKeyParameters) publicKey).getParameters().getParameters());
82   
83           Element[][] result = new Element[2][n];
84           Random random = new Random();
85           for (int i = 0; i < n; i += 2) {
86               if (random.nextBoolean()) {
87                   result[0][i] = pairing.getZr().newZeroElement();
88                   result[0][i + 1] = pairing.getZr().newZeroElement();
89   
90                   result[1][i] = pairing.getZr().newRandomElement();
91                   result[1][i + 1] = pairing.getZr().newRandomElement();
92               } else {
93                   result[0][i] = pairing.getZr().newOneElement();
94                   result[0][i + 1] = pairing.getZr().newRandomElement();
95   
96                   result[1][i] = result[0][i + 1].duplicate().negate();
97                   result[1][i + 1] = pairing.getZr().newOneElement();
98               }
99           }
100          return result;
101      }
102  
103      public Element[][] createNonOrthogonalVectors(CipherParameters publicKey, int n) {
104          Pairing pairing = PairingFactory.getPairing(((IPLOSTW10PublicKeyParameters) publicKey).getParameters().getParameters());
105  
106          Element[][] result = new Element[2][n];
107          for (int i = 0; i < n; i += 2) {
108              result[0][i] = pairing.getZr().newOneElement();
109              result[0][i + 1] = pairing.getZr().newRandomElement();
110  
111              result[1][i] = pairing.getZr().newOneElement().sub(result[0][i + 1]);
112              result[1][i + 1] = pairing.getZr().newOneElement();
113          }
114          return result;
115      }
116  
117  
118  
119      public static void main(String[] args) {
120          IPLOSTW10 iplostw10 = new IPLOSTW10();
121  
122          int n = 2;
123  
124          // Setup
125          AsymmetricCipherKeyPair keyPair = iplostw10.setup(n);
126  
127          // Test for orthogonal vectors
128          Element[][] vectors = iplostw10.createOrthogonalVectors(keyPair.getPublic(), n);
129          assertEquals(true,
130                  iplostw10.test(
131                          iplostw10.keyGen(keyPair.getPrivate(), vectors[1]),
132                          iplostw10.encrypt(keyPair.getPublic(), vectors[0])
133                  )
134          );
135  
136          // Test for non-orthogonal vectors
137          vectors = iplostw10.createNonOrthogonalVectors(keyPair.getPublic(), n);
138          assertEquals(false,
139                  iplostw10.test(
140                          iplostw10.keyGen(keyPair.getPrivate(), vectors[1]),
141                          iplostw10.encrypt(keyPair.getPublic(), vectors[0])
142                  )
143          );
144      }
145  
146  
147  }