├── .gitignore
├── LICENSE
├── README.md
├── build.xml
├── javacc
├── LICENSE
└── bin
│ └── lib
│ └── javacc.jar
├── pom.xml
└── src
├── main
├── java
│ ├── META-INF
│ │ └── MANIFEST.MF
│ └── trabe
│ │ ├── AbeDecryptionException.java
│ │ ├── AbeEncrypted.java
│ │ ├── AbeEncryptionException.java
│ │ ├── AbeInputStream.java
│ │ ├── AbeOutputStream.java
│ │ ├── AbePrivateKey.java
│ │ ├── AbePublicKey.java
│ │ ├── AbeSecretMasterKey.java
│ │ ├── AbeSettings.java
│ │ ├── AbeUserIndex.java
│ │ ├── Cpabe.java
│ │ ├── CpabeWeber.java
│ │ ├── DecryptionBlackBox.java
│ │ ├── DecryptionException.java
│ │ ├── ElementVector.java
│ │ ├── MockBlackBox.java
│ │ ├── Pair.java
│ │ ├── aes
│ │ ├── AesDecryptionException.java
│ │ ├── AesEncryption.java
│ │ └── InputStreamStopper.java
│ │ ├── benchmark
│ │ ├── Benchmark.java
│ │ ├── BenchmarkResult.java
│ │ ├── BenchmarkRunner.java
│ │ ├── CpabeDecryptionAndAttributeNumberTest.java
│ │ ├── CpabeDecryptionOrAttributeNumberTest.java
│ │ ├── CpabeEncryptionAttributeNumberTest.java
│ │ └── CpabeKeygenAttributeNumberTest.java
│ │ ├── demo
│ │ ├── BlackBoxDemo.java
│ │ └── DemoForCpabe.java
│ │ ├── lw14
│ │ ├── CipherText.java
│ │ ├── Lw14.java
│ │ ├── Lw14DecryptionBlackBox.java
│ │ ├── Lw14MockBlackBox.java
│ │ ├── Lw14Polynomial.java
│ │ ├── Lw14PrivateKeyComponent.java
│ │ ├── Lw14Util.java
│ │ ├── SortedPowerSet.java
│ │ ├── SortedPowerSetIterator.java
│ │ └── policy
│ │ │ ├── LsssMatrix.java
│ │ │ ├── LsssMatrixCell.java
│ │ │ ├── Lw14PolicyAbstractNode.java
│ │ │ ├── Lw14PolicyLeafNode.java
│ │ │ ├── Lw14PolicyParentNode.java
│ │ │ └── Lw14TreePreprocessing.java
│ │ ├── matrixElimination
│ │ ├── ElementField.java
│ │ ├── Field.java
│ │ └── Matrix.java
│ │ └── policy
│ │ ├── AttributeParser.java
│ │ ├── PolicyParsing.java
│ │ └── Util.java
└── resources
│ ├── ASTAttribute.java
│ ├── ASTExpression.java
│ ├── ASTGeoHashAttribute.java
│ ├── ASTNumericalAttribute.java
│ ├── ASTOf.java
│ └── policyTree.jjt
└── test
└── java
└── trabe
└── tests
├── AesTest.java
├── AllTests.java
├── BlackBoxTest.java
├── ElementVectorTest.java
├── LsssTest.java
├── Lw14Test.java
├── ParserTest.java
├── TestUtil.java
└── WeberTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | #*.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
14 | *.iml
15 | *.ipr
16 | *.iws
17 |
18 | tmp/
19 | examples/
20 | testFolder/
21 | target/
22 | out/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jTR-ABE
2 | Traceable and Revocable Attribute-based Encryption in Java
3 |
4 | This software package implements an ABE scheme by Liu and Wong: [Practical Attribute-Based Encryption: Traitor Tracing, Revocation, and Large Universe](http://eprint.iacr.org/2014/616). The flavor is Ciphertext-Policy (CP-ABE).
5 | The implementation supports non-monotonic access structures (AC), which is not part this scheme. We borrow techniques from Yamada et al. (http://eprint.iacr.org/2014/181) to achieve this property.
6 |
7 | #### Notes
8 |
9 | jTR-ABE is a rewrite of an early version of [JCPABE](https://github.com/TU-Berlin-SNET/JCPABE) which itself is a complete rewrite of an earlier Java [cpabe](https://github.com/junwei-wang/cpabe) implementation) which is a port of Bethencourt's [libbswabe](http://hms.isi.jhu.edu/acsc/cpabe/).
10 |
11 | It supports
12 |
13 | - Traceability of traitors (publishers of decryption keys or decryption boxes),
14 | - User revocation,
15 | - Policies with expressive threshold or boolean formulas and numerical attributes.
16 |
17 | The main functionality is accessible in the trabe.Cpabe class.
18 |
19 | This is research software and should not be used in application where actual security is required.
20 |
21 | #### Dependencies
22 | Download the source of JPBC from [here](http://sourceforge.net/p/jpbc/code/) (JCPABE has only been tested with version 2.0.0).
23 | Install it into your local maven repository using
24 | ```sh
25 | $ mvn install
26 | ```
27 | (only the sub projects jpbc-plaf, jpbc-api and jpbc-pbc are needed)
28 |
29 | It is also recommended to install the PBC wrapper for JPBC to improve the performance (as explained [here](http://gas.dia.unisa.it/projects/jpbc/docs/pbcwrapper.html)). Note: in Ubuntu the GMP dependency package is called libgmp10.
30 |
31 |
32 | #### Build
33 | To build jTR-ABE:
34 | ```sh
35 | $ mvn compile
36 | ```
37 |
38 | To install it into a local maven repository run:
39 | ```sh
40 | $ mvn install
41 | ```
42 |
43 |
44 | #### Common Problems
45 |
46 | JPBC-PBC library can not be found or loaded:
47 | Remove the system JNA library or patch JPBC to work with newest JNA.
48 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Builds the parser for jCPABE
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/javacc/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2006, Sun Microsystems, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the Sun Microsystems, Inc. nor the names of its
13 | contributors may be used to endorse or promote products derived from
14 | this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 | THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 |
--------------------------------------------------------------------------------
/javacc/bin/lib/javacc.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TU-Berlin-SNET/jTR-ABE/f783f2ea263318d73879cac9cf022f764d3e720e/javacc/bin/lib/javacc.jar
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | snet.abe
6 | trabe
7 | jar
8 | 1.0.0-SNAPSHOT
9 |
10 | trabe
11 |
12 |
13 | maven-restlet
14 | Restlet repository
15 | http://maven.restlet.com
16 |
17 |
18 | SNET butyeboi
19 |
20 | http://www.user.tu-berlin.de/thatmann/mvn/public
21 |
22 | always
23 |
24 |
25 |
26 |
27 |
28 | UTF-8
29 |
30 |
31 |
32 |
33 |
34 |
35 | org.eclipse.m2e
36 | lifecycle-mapping
37 | 1.0.0
38 |
39 |
40 |
41 |
42 |
43 | org.apache.maven.plugins
44 | maven-antrun-plugin
45 | 1.7
46 |
47 | run
48 |
49 |
50 |
51 |
52 | false
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | false
65 | src/main/java
66 |
67 | **
68 |
69 |
70 | **/*.java
71 |
72 |
73 |
74 |
75 |
76 | org.apache.maven.plugins
77 | maven-compiler-plugin
78 | 3.1
79 |
80 | 1.6
81 | 1.6
82 |
83 |
84 |
85 | maven-antrun-plugin
86 | 1.7
87 |
88 |
89 | generate-sources
90 |
91 |
92 |
93 |
94 |
95 |
96 | run
97 |
98 |
99 |
100 |
101 |
102 | org.codehaus.mojo
103 | build-helper-maven-plugin
104 | 1.9
105 |
106 |
107 | generate-sources
108 |
109 | add-source
110 |
111 |
112 |
113 | src/gen/java
114 |
115 |
116 |
117 |
118 |
119 |
120 | org.codehaus.mojo
121 | versions-maven-plugin
122 | 2.1
123 |
124 |
125 | org.codehaus.mojo
126 | cobertura-maven-plugin
127 | 2.7
128 |
129 |
130 | html
131 | xml
132 |
133 |
134 |
135 |
136 |
137 | org.apache.maven.plugins
138 | maven-source-plugin
139 |
140 |
141 | attach-sources
142 |
143 | jar
144 |
145 |
146 |
147 |
148 |
149 | org.apache.maven.plugins
150 | maven-javadoc-plugin
151 |
152 |
153 | attach-javadocs
154 |
155 | jar
156 |
157 |
158 |
159 |
160 | trabe.policyparser.*
161 |
162 |
163 |
164 | org.apache.maven.plugins
165 | maven-assembly-plugin
166 | 2.5.5
167 |
168 |
169 | jar-with-dependencies
170 |
171 |
172 |
173 | true
174 | trabe.benchmark.BenchmarkRunner
175 |
176 |
177 |
178 |
179 |
180 | assemble-all
181 | package
182 |
183 | single
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 | it.unisa.dia.gas
194 | jpbc-api
195 | 2.0.0
196 |
197 |
198 | it.unisa.dia.gas
199 | jpbc-plaf
200 | 2.0.0
201 |
202 |
203 | it.unisa.dia.gas
204 | jpbc-pbc
205 | 2.0.0
206 |
207 |
208 | ch.hsr
209 | geohash
210 | 1.0.10
211 |
212 |
213 | junit
214 | junit
215 | 4.11
216 | true
217 |
218 |
219 | org.bouncycastle
220 | bcprov-jdk15on
221 | 1.51
222 |
223 |
224 | net.java.dev.jna
225 | jna
226 | 4.1.0
227 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/src/main/java/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: trabe.demo.BlackBoxDemo
3 |
4 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeDecryptionException.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | public class AbeDecryptionException extends DecryptionException {
4 |
5 | private static final long serialVersionUID = 2848983353356933397L;
6 |
7 | public AbeDecryptionException(String msg) {
8 | super(msg);
9 | }
10 |
11 | public AbeDecryptionException(String msg, Throwable t) {
12 | super(msg, t);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeEncrypted.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | import java.io.*;
6 |
7 | import trabe.aes.AesDecryptionException;
8 | import trabe.aes.AesEncryption;
9 | import trabe.lw14.CipherText;
10 | import trabe.lw14.Lw14;
11 |
12 | /**
13 | * The AbeEncrypted object can only be used once per method, because it is based
14 | * on streams and the streams cannot be read anew.
15 | */
16 | public class AbeEncrypted {
17 | private final CipherText cipher;
18 | private final byte[] iv;
19 | private final InputStream dataStream; // the encrypted data
20 |
21 | AbeEncrypted(byte[] iv, CipherText cipher, InputStream dataStream) {
22 | this.iv = iv;
23 | this.cipher = cipher;
24 | this.dataStream = dataStream;
25 | }
26 |
27 | public CipherText getCipher() {
28 | return cipher;
29 | }
30 |
31 | public void writeEncryptedFile(OutputStream out, AbePublicKey publicKey) throws IOException {
32 | AbeOutputStream abeOut = new AbeOutputStream(out, publicKey);
33 | cipher.writeToStream(abeOut);
34 | abeOut.writeInt(iv.length);
35 | abeOut.write(iv);
36 | byte[] buffer = new byte[1024];
37 | int len;
38 | while ((len = dataStream.read(buffer)) != -1) {
39 | abeOut.write(buffer, 0, len);
40 | }
41 | }
42 |
43 | public static AbeEncrypted readFromFile(AbePublicKey publicKey, File file) throws IOException {
44 | return AbeEncrypted.readFromStream(publicKey, new BufferedInputStream(new FileInputStream(file)));
45 | }
46 |
47 | public static AbeEncrypted readFromStream(AbePublicKey publicKey, InputStream input) throws IOException {
48 | AbeInputStream stream = new AbeInputStream(input, publicKey);
49 | CipherText cipher = CipherText.readFromStream(stream);
50 | int ivLength = stream.readInt();
51 | byte[] iv = new byte[ivLength];
52 | stream.readFully(iv);
53 | return new AbeEncrypted(iv, cipher, input);
54 | }
55 |
56 | /**
57 | * Writes the plaintext (decrypts) from the internal ciphertext stream.
58 | *
59 | * @param privateKey Private key
60 | * @param output Output stream
61 | * @throws AbeDecryptionException See {@link #writeDecryptedData(AbePrivateKey, byte[], OutputStream)}
62 | * @throws IOException See {@link #writeDecryptedData(AbePrivateKey, byte[], OutputStream)}
63 | */
64 | public void writeDecryptedData(AbePrivateKey privateKey, OutputStream output) throws AbeDecryptionException, IOException {
65 | writeDecryptedData(privateKey, null, output);
66 | }
67 |
68 | /**
69 | * Writes the plaintext (decrypts) from the internal ciphertext stream.
70 | *
71 | * @param privateKey Private key
72 | * @param lbeKey Location-based key
73 | * @param output Output stream
74 | * @throws AbeDecryptionException Decryption failed
75 | * @throws IOException Problem with reading the ciphertext or writing the plaintext
76 | */
77 | public void writeDecryptedData(AbePrivateKey privateKey, byte[] lbeKey, OutputStream output)
78 | throws AbeDecryptionException, IOException {
79 | Element secret = Lw14.decrypt(privateKey, cipher);
80 | if (secret == null) {
81 | throw new AbeDecryptionException("Couldn't recover the secret");
82 | }
83 | byte[] cpabeKey = secret.toBytes();
84 | try {
85 | AesEncryption.decrypt(cpabeKey, lbeKey, iv, dataStream, output);
86 | } catch (AesDecryptionException e) {
87 | throw new AbeDecryptionException("AES ciphertext couldn't be decrypted", e);
88 | }
89 | dataStream.close();
90 | }
91 |
92 | public byte[] writeDecryptedData(AbePrivateKey privateKey) throws IOException, AbeDecryptionException {
93 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
94 | AbeOutputStream stream = new AbeOutputStream(baos, privateKey.getPublicKey());
95 | writeDecryptedData(privateKey, stream);
96 | return baos.toByteArray();
97 | }
98 |
99 | public byte[] writeEncryptedData(AbePublicKey pub) throws IOException, AbeDecryptionException {
100 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
101 | AbeOutputStream stream = new AbeOutputStream(baos, pub);
102 | writeEncryptedFile(stream, pub);
103 | return baos.toByteArray();
104 | }
105 |
106 | public static AbeEncrypted read(byte[] data, AbePublicKey pub) throws IOException {
107 | AbeInputStream stream = new AbeInputStream(new ByteArrayInputStream(data), pub);
108 | return readFromStream(pub, stream);
109 | }
110 |
111 | public static AbeEncrypted createDuringEncryption(byte[] iv, CipherText cipher, InputStream input, Element plainSecret) throws AbeEncryptionException, IOException {
112 | return new AbeEncrypted(iv, cipher, AesEncryption.encrypt(plainSecret.toBytes(), null, iv, input));
113 | }
114 |
115 | public static AbeEncrypted createDuringEncryption(byte[] iv, byte[] lbeKey, CipherText cipher, InputStream input, Element plainSecret) throws AbeEncryptionException, IOException {
116 | return new AbeEncrypted(iv, cipher, AesEncryption.encrypt(plainSecret.toBytes(), lbeKey, iv, input));
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeEncryptionException.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import java.security.GeneralSecurityException;
4 |
5 | public class AbeEncryptionException extends GeneralSecurityException {
6 |
7 | private static final long serialVersionUID = 1043863535572140323L;
8 |
9 | public AbeEncryptionException(String msg) {
10 | super(msg);
11 | }
12 |
13 | public AbeEncryptionException(String msg, Throwable t) {
14 | super(msg, t);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeInputStream.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | import java.io.DataInputStream;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 |
9 | public class AbeInputStream extends DataInputStream {
10 | private final String PUB_MISSING_ERROR = "Can't read Elements without the public master key.";
11 |
12 | private AbePublicKey publicKey;
13 |
14 | public AbeInputStream(InputStream in, AbePublicKey publicKey) {
15 | super(in);
16 | this.publicKey = publicKey;
17 | }
18 |
19 | /**
20 | * If you use this constructor you need to manually set the public key before reading any elements.
21 | *
22 | * @param in Underlying input stream
23 | */
24 | public AbeInputStream(InputStream in) {
25 | this(in, null);
26 | }
27 |
28 | public void setPublicKey(AbePublicKey pubKey) {
29 | this.publicKey = pubKey;
30 | }
31 |
32 | // only used for the curve parameters and attributes, no need for fancy encodings
33 | // since internal attribute representation only uses [a-zA-Z0-9:_]
34 | public String readString() throws IOException {
35 | int length = readInt();
36 | byte[] bytes = new byte[length];
37 | readFully(bytes);
38 | return new String(bytes, AbeSettings.STRINGS_LOCALE);
39 | }
40 |
41 | public Element readElement() throws IOException {
42 | if (readBoolean()) {
43 | return null;
44 | }
45 | if (publicKey == null) throw new IOException(PUB_MISSING_ERROR);
46 | int fieldIndex = readInt();
47 | int length = readInt();
48 | byte[] bytes = new byte[length];
49 | readFully(bytes);
50 | Element e = publicKey.getPairing().getFieldAt(fieldIndex).newElementFromBytes(bytes);
51 |
52 | // this is a workaround because it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement does not serialize the infFlag
53 | boolean instOfCurveElementAndInf = readBoolean();
54 | if (instOfCurveElementAndInf) {
55 | //e.setToZero(); // according to the code this simply sets the infFlag to 1
56 | throw new IOException("The point is infinite. This shouldn't happen.");
57 | }
58 | return e;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeOutputStream.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 | import it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement;
5 |
6 | import java.io.DataOutputStream;
7 | import java.io.IOException;
8 | import java.io.OutputStream;
9 |
10 | public class AbeOutputStream extends DataOutputStream {
11 |
12 | private final AbePublicKey pubKey;
13 |
14 | public AbeOutputStream(OutputStream out, AbePublicKey pubKey) {
15 | super(out);
16 | this.pubKey = pubKey;
17 | }
18 |
19 | // only used for the curve parameters and attributes, no need for fancy encodings
20 |
21 | /**
22 | * Writes a string to the stream with the locale specified in
23 | * {@link AbeSettings#STRINGS_LOCALE} and prepends the length of the
24 | * serialized bytes.
25 | * @param string String to write
26 | * @throws IOException see {@link #write(byte[])}
27 | */
28 | public void writeString(String string) throws IOException {
29 | byte[] bytes = string.getBytes(AbeSettings.STRINGS_LOCALE);
30 | writeInt(bytes.length);
31 | write(bytes);
32 | }
33 |
34 | public void writeElement(Element elem) throws IOException {
35 | writeBoolean(elem == null);
36 | if (elem == null) {
37 | return;
38 | }
39 | writeInt(pubKey.getPairing().getFieldIndex(elem.getField()));
40 | byte[] bytes = elem.toBytes();
41 | writeInt(bytes.length);
42 | write(bytes);
43 |
44 | // this is a workaround because it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement does not serialize the infFlag
45 | writeBoolean(elem instanceof CurveElement && elem.isZero());
46 | if (elem instanceof CurveElement && elem.isZero()) {
47 | throw new IOException("Infinite element detected. They should not happen.");
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbePrivateKey.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import java.io.*;
4 | import java.util.*;
5 |
6 | import it.unisa.dia.gas.jpbc.ElementPowPreProcessing;
7 | import it.unisa.dia.gas.jpbc.PairingPreProcessing;
8 | import trabe.lw14.Lw14PrivateKeyComponent;
9 | import it.unisa.dia.gas.jpbc.Element;
10 | import trabe.lw14.Lw14Util;
11 |
12 | public class AbePrivateKey {
13 | private static final int SERIALIZE_VERSION = 3;
14 |
15 | public final AbeUserIndex position;
16 |
17 | /** G1 **/
18 | public final Element k1_ij;
19 | /** G1 **/
20 | public final Element k2_ij;
21 | /** G1 **/
22 | public final Element k3_ij;
23 | /** [G1] **/
24 | public final Element[] k_ijj;
25 | private final ArrayList components;
26 | private final AbePublicKey pubKey;
27 |
28 | public PairingPreProcessing k2_ij_pp = null;
29 |
30 | /**
31 | * Can be used to store additional information such as a secret seed or a
32 | * authority public key. The seed on the client that can be used
33 | * to seed a PRNG for generating common parameters on client and authority
34 | * without further communication. The public key can be used to verify
35 | * received data that it is indeed from the authority.
36 | */
37 | private final Map additionalData = new HashMap();
38 |
39 | public AbePrivateKey(AbeUserIndex position,
40 | Element k1_ij, Element k2_ij, Element k3_ij,
41 | Element[] k_ijj, ArrayList components,
42 | AbePublicKey pubKey) {
43 | this.position = position;
44 | this.k1_ij = k1_ij;
45 | this.k2_ij = k2_ij;
46 | this.k3_ij = k3_ij;
47 | this.k_ijj = k_ijj;
48 | this.components = components;
49 | this.pubKey = pubKey;
50 | }
51 |
52 | public AbePublicKey getPublicKey() {
53 | return pubKey;
54 | }
55 |
56 | /**
57 | * @return a new privatekey, where d and the component list has been duplicated. The list elements have NOT been duplicated.
58 | */
59 | public AbePrivateKey duplicate() {
60 | ArrayList duplicatedComponents = new ArrayList(components.size());
61 | for (Lw14PrivateKeyComponent cur : components) {
62 | // should each component also be duplicated? only necessary if components are altered somewhere, which they are not
63 | duplicatedComponents.add(cur);
64 | }
65 | Element[] duplicatedK_ijj = new Element[k_ijj.length];
66 | for(int i = 0; i < k_ijj.length; i++) {
67 | if (k_ijj[i] == null) {
68 | duplicatedK_ijj[i] = null;
69 | } else {
70 | duplicatedK_ijj[i] = k_ijj[i].duplicate();
71 | }
72 | }
73 | AbePrivateKey sk = new AbePrivateKey(position, k1_ij.duplicate(), k2_ij.duplicate(),
74 | k3_ij.duplicate(), duplicatedK_ijj, duplicatedComponents, pubKey);
75 |
76 | sk.additionalData.putAll(this.additionalData);
77 |
78 | return sk;
79 | }
80 |
81 | /**
82 | * Return the attributes of the matrix (LSSS approach).
83 | * @return Attributes in the matrix
84 | */
85 | public Set getAttributeSet() {
86 | int attributes = getComponents().size();
87 | Set set = new HashSet(attributes);
88 | for(int i = 0; i < attributes; i++) {
89 | set.add(components.get(i).attribute);
90 | }
91 | return set;
92 | }
93 |
94 | public List getComponents() {
95 | return components;
96 | }
97 |
98 | /**
99 | * Finds the key component by attribute. This is of the LSSS approach which
100 | * needs access to the attribute string directly.
101 | * @param attribute Attribute string
102 | * @return Attribute component
103 | */
104 | public Lw14PrivateKeyComponent getComponent(String attribute) {
105 | for(Lw14PrivateKeyComponent c : components){
106 | if (attribute.equals(c.attribute)) {
107 | return c;
108 | }
109 | }
110 | return null;
111 | }
112 |
113 | public Lw14PrivateKeyComponent getSatisfyingComponent(Element hashedAttribute) {
114 | for (int i = 0; i < components.size(); i++) {
115 | Lw14PrivateKeyComponent component = components.get(i);
116 | if (component.hashedAttributeZr.isEqual(hashedAttribute)) {
117 | return component;
118 | }
119 | }
120 | return null;
121 | }
122 |
123 | /**
124 | * @see java.util.Map#get(Object)
125 | * @param name Additional data identifier
126 | * @return Additional data
127 | */
128 | public byte[] getAdditionalData(String name) {
129 | return additionalData.get(name);
130 | }
131 |
132 | /**
133 | * @see java.util.Map#put(Object, Object)
134 | * @param name Additional data identifier
135 | * @param data Additional data
136 | * @return previously stored/replaced additional data or null
137 | */
138 | public byte[] setAdditionalData(String name, byte[] data) {
139 | return additionalData.put(name, data);
140 | }
141 |
142 | public AbePrivateKey newKeyWithAddedAttributes(List newComponents) {
143 | AbePrivateKey newKey = this.duplicate();
144 | newKey.components.addAll(newComponents);
145 | return newKey;
146 | }
147 |
148 | /**
149 | * Produces a new private key object which contains all the other attribute
150 | * components. It returns null if the positions or the other elements don't match.
151 | * The additional data values will be replaced.
152 | * @param otherKey Private to merge with (attributes are taken from this one)
153 | * @return Entirely new private key
154 | */
155 | public AbePrivateKey merge(AbePrivateKey otherKey) {
156 | if (otherKey == null
157 | || !k1_ij.equals(otherKey.k1_ij)
158 | || !k2_ij.equals(otherKey.k2_ij)
159 | || !k3_ij.equals(otherKey.k3_ij)
160 | || !Arrays.equals(k_ijj, otherKey.k_ijj)
161 | || !position.equals(otherKey.position)) {
162 | return null;
163 | }
164 | AbePrivateKey newKey = duplicate();
165 | newKey.components.addAll(otherKey.getComponents());
166 | newKey.additionalData.putAll(otherKey.additionalData);
167 | return newKey;
168 | }
169 |
170 | public static AbePrivateKey readFromStream(AbeInputStream stream) throws IOException {
171 | int version = stream.readInt();
172 | AbePublicKey pubKey = AbePublicKey.readFromStream(stream);
173 | stream.setPublicKey(pubKey);
174 | int m = stream.readInt();
175 | int counter = stream.readInt();
176 | Element k1_ij = stream.readElement();
177 | Element k2_ij = stream.readElement();
178 | Element k3_ij = stream.readElement();
179 |
180 | Element[] k_ijj = Lw14Util.readElementArray(stream);
181 |
182 | byte[] secretSeed = null;
183 | if (version == 1) {
184 | secretSeed = Lw14Util.readByteArray(stream);
185 | }
186 |
187 | int compsLength = stream.readInt();
188 | ArrayList components = new ArrayList(compsLength);
189 |
190 | for (int i = 0; i < compsLength; i++) {
191 | components.add(Lw14PrivateKeyComponent.readFromStream(stream, version));
192 | }
193 | AbePrivateKey sk = new AbePrivateKey(new AbeUserIndex(m, counter), k1_ij, k2_ij, k3_ij, k_ijj,
194 | components, pubKey);
195 |
196 | if (version == 1) {
197 | sk.setAdditionalData("secretSeed", secretSeed);
198 | } else {
199 | int adLength = stream.readInt();
200 | for (int i = 0; i < adLength; i++) {
201 | String name = stream.readString();
202 | byte[] data = Lw14Util.readByteArray(stream);
203 |
204 | sk.setAdditionalData(name, data);
205 | }
206 | }
207 | return sk;
208 | }
209 |
210 | public static AbePrivateKey readFromStream(InputStream stream) throws IOException {
211 | return readFromStream(new AbeInputStream(stream));
212 | }
213 |
214 | public static AbePrivateKey readFromFile(File file) throws IOException {
215 | FileInputStream stream = new FileInputStream(file);
216 | AbePrivateKey priv = readFromStream(stream);
217 | stream.close();
218 | return priv;
219 | }
220 |
221 | public void writeToFile(File file) throws IOException {
222 | FileOutputStream stream = new FileOutputStream(file);
223 | writeToStream(stream);
224 | stream.close();
225 | }
226 |
227 | public void writeToStream(OutputStream stream) throws IOException {
228 | writeToStream(new AbeOutputStream(stream, pubKey));
229 | }
230 |
231 | public void writeToStream(AbeOutputStream stream) throws IOException {
232 | stream.writeInt(SERIALIZE_VERSION);
233 | pubKey.writeToStream(stream);
234 | stream.writeInt(position.m);
235 | stream.writeInt(position.counter);
236 | stream.writeElement(k1_ij);
237 | stream.writeElement(k2_ij);
238 | stream.writeElement(k3_ij);
239 |
240 | Lw14Util.writeArray(k_ijj, stream);
241 |
242 | stream.writeInt(components.size());
243 | for (Lw14PrivateKeyComponent component : components) {
244 | component.writeToStream(stream);
245 | }
246 |
247 | stream.writeInt(additionalData.size());
248 | for (Map.Entry e : additionalData.entrySet()) {
249 | stream.writeString(e.getKey());
250 | Lw14Util.writeArray(e.getValue(), stream);
251 | }
252 | }
253 |
254 | public byte[] getAsByteArray() throws IOException {
255 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
256 | this.writeToStream(baos);
257 | return baos.toByteArray();
258 | }
259 |
260 | public static AbePrivateKey readFromByteArray(byte[] data) throws IOException {
261 | AbeInputStream stream = new AbeInputStream(new ByteArrayInputStream(data));
262 | try {
263 | return readFromStream(stream);
264 | } finally {
265 | stream.close();
266 | }
267 | }
268 |
269 | @Override
270 | public boolean equals(Object obj) {
271 | if (obj == null || !(obj instanceof AbePrivateKey)) {
272 | return false;
273 | } else if(this == obj) {
274 | return true;
275 | }
276 | AbePrivateKey p = (AbePrivateKey)obj;
277 |
278 | boolean result = pubKey.equals(p.pubKey);
279 | result = result && position.equals(p.position);
280 | result = result && k1_ij.equals(p.k1_ij);
281 | result = result && k2_ij.equals(p.k2_ij);
282 | result = result && k3_ij.equals(p.k3_ij);
283 | result = result && Arrays.equals(k_ijj, p.k_ijj);
284 | result = result && Arrays.equals(components.toArray(), p.components.toArray());
285 | result = result && additionalData.size() == p.additionalData.size();
286 | for (Map.Entry dataEntry : additionalData.entrySet()) {
287 | if (!p.additionalData.containsKey(dataEntry.getKey()) ||
288 | !Arrays.equals(dataEntry.getValue(), p.additionalData.get(dataEntry.getKey()))) {
289 | result = false;
290 | break;
291 | }
292 | }
293 |
294 | return result;
295 | }
296 |
297 | public static int getSerializeVersion() {
298 | return SERIALIZE_VERSION;
299 | }
300 | }
--------------------------------------------------------------------------------
/src/main/java/trabe/AbePublicKey.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import java.io.*;
4 | import java.util.Arrays;
5 |
6 | import it.unisa.dia.gas.jpbc.Element;
7 | import it.unisa.dia.gas.jpbc.Pairing;
8 | import it.unisa.dia.gas.jpbc.PairingParameters;
9 | import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
10 | import it.unisa.dia.gas.plaf.jpbc.pairing.parameters.PropertiesParameters;
11 | import trabe.lw14.Lw14Util;
12 |
13 | public class AbePublicKey {
14 | private static final int SERIALIZE_VERSION = 1;
15 |
16 | /*
17 | * A public key
18 | */
19 | private final String pairingDesc;
20 | private transient Pairing p;
21 | /** G_1 **/
22 | public Element g;
23 | /** G_1 **/
24 | public Element h;
25 | /** G_1 **/
26 | public Element f;
27 | /** [G_1] **/
28 | public Element[] f_j;
29 | /** G_1 **/
30 | public Element G;
31 | /** G_1 **/
32 | public Element H;
33 | /** [G_T] **/
34 | public Element[] E_i;
35 | /** [G_1] **/
36 | public Element[] G_i;
37 | /** [G_1] **/
38 | public Element[] Z_i;
39 | /** [G_1] **/
40 | public Element[] H_j;
41 | /** [G'] **/
42 | public Element Gquote;
43 | /**
44 | * Creates a new AbePublicKey. This key should only be used after the elements have been set (setElements).
45 | *
46 | * @param pairingDescription Description of the pairing (parameters)
47 | */
48 | public AbePublicKey(String pairingDescription) {
49 | this.pairingDesc = pairingDescription;
50 | }
51 |
52 | public String getPairingDescription() {
53 | return pairingDesc;
54 | }
55 |
56 | public int getMaxUsers() {
57 | return getSqrtUsers() * getSqrtUsers() - 1;
58 | }
59 |
60 | public Pairing getPairing() {
61 | if (p == null) {
62 | PairingParameters params = new PropertiesParameters().load(new ByteArrayInputStream(pairingDesc.getBytes()));
63 | p = PairingFactory.getPairing(params);
64 | }
65 | return p;
66 | }
67 |
68 | public void setElements(Element g, Element h, Element f, Element[] f_j,
69 | Element G, Element H, Element[] E_i, Element[] G_i,
70 | Element[] Z_i, Element[] H_j, Element Gquote) {
71 | this.g = g;
72 | this.h = h;
73 | this.f = f;
74 | this.f_j = f_j;
75 | this.G = G;
76 | this.H = H;
77 | this.E_i = E_i;
78 | this.G_i = G_i;
79 | this.Z_i = Z_i;
80 | this.H_j = H_j;
81 | this.Gquote = Gquote;
82 | }
83 |
84 | public static AbePublicKey readFromFile(File file) throws IOException {
85 | AbeInputStream stream = new AbeInputStream(new FileInputStream(file));
86 | try {
87 | return readFromStream(stream);
88 | } finally {
89 | stream.close();
90 | }
91 | }
92 |
93 | public static AbePublicKey readFromStream(AbeInputStream stream) throws IOException {
94 | int version = stream.readInt();
95 |
96 | String pairingDescription = stream.readString();
97 | AbePublicKey publicKey = new AbePublicKey(pairingDescription);
98 | stream.setPublicKey(publicKey);
99 |
100 | int usersSqrt = stream.readInt();
101 |
102 | publicKey.g = stream.readElement();
103 | publicKey.h = stream.readElement();
104 | publicKey.f = stream.readElement();
105 | publicKey.G = stream.readElement();
106 | publicKey.H = stream.readElement();
107 |
108 | publicKey.f_j = Lw14Util.readElementArray(usersSqrt, stream);
109 | publicKey.E_i = Lw14Util.readElementArray(usersSqrt, stream);
110 | publicKey.G_i = Lw14Util.readElementArray(usersSqrt, stream);
111 | publicKey.Z_i = Lw14Util.readElementArray(usersSqrt, stream);
112 | publicKey.H_j = Lw14Util.readElementArray(usersSqrt, stream);
113 |
114 | return publicKey;
115 | }
116 |
117 | public void writeToStream(OutputStream stream) throws IOException {
118 | writeToStream(new AbeOutputStream(stream, this));
119 | }
120 |
121 | public void writeToStream(AbeOutputStream stream) throws IOException {
122 | stream.writeInt(SERIALIZE_VERSION);
123 |
124 | stream.writeString(pairingDesc);
125 |
126 | stream.writeInt(f_j.length);
127 |
128 | stream.writeElement(g);
129 | stream.writeElement(h);
130 | stream.writeElement(f);
131 | stream.writeElement(G);
132 | stream.writeElement(H);
133 |
134 | Lw14Util.writeArray(f_j, stream, false);
135 | Lw14Util.writeArray(E_i, stream, false);
136 | Lw14Util.writeArray(G_i, stream, false);
137 | Lw14Util.writeArray(Z_i, stream, false);
138 | Lw14Util.writeArray(H_j, stream, false);
139 | }
140 |
141 | public void writeToFile(File file) throws IOException {
142 | AbeOutputStream fos = new AbeOutputStream(new FileOutputStream(file), this);
143 | writeToStream(fos);
144 | fos.close();
145 | }
146 |
147 | public byte[] getAsByteArray() throws IOException {
148 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
149 | this.writeToStream(baos);
150 | return baos.toByteArray();
151 | }
152 |
153 | public static AbePublicKey readFromByteArray(byte[] data) throws IOException {
154 | AbeInputStream stream = new AbeInputStream(new ByteArrayInputStream(data));
155 | try {
156 | return readFromStream(stream);
157 | } finally {
158 | stream.close();
159 | }
160 | }
161 |
162 | public int getSqrtUsers(){
163 | return this.f_j.length;
164 | }
165 |
166 | @Override
167 | public boolean equals(Object obj) {
168 | if (obj == null || !(obj instanceof AbePublicKey)) {
169 | return false;
170 | } else if(this == obj) {
171 | return true;
172 | }
173 | AbePublicKey p = (AbePublicKey)obj;
174 |
175 | boolean result = pairingDesc.equals(p.pairingDesc);
176 | result = result && g.equals(p.g);
177 | result = result && h.equals(p.h);
178 | result = result && f.equals(p.f);
179 | result = result && Arrays.equals(f_j, p.f_j);
180 | result = result && G.equals(p.G);
181 | result = result && H.equals(p.H);
182 | result = result && Arrays.equals(E_i, p.E_i);
183 | result = result && Arrays.equals(G_i, p.G_i);
184 | result = result && Arrays.equals(Z_i, p.Z_i);
185 | result = result && Arrays.equals(H_j, p.H_j);
186 |
187 | return result;
188 | }
189 |
190 | @Override
191 | public String toString() {
192 | StringBuilder sb = new StringBuilder();
193 | sb.append("{\n");
194 |
195 | sb.append(" \"pairingDesc\":");
196 | sb.append('"');
197 | sb.append(pairingDesc);
198 | sb.append('"');
199 | sb.append(",\n");
200 |
201 | sb.append(" \"g\":");
202 | sb.append('"');
203 | sb.append(g);
204 | sb.append('"');
205 | sb.append(",\n");
206 |
207 | sb.append(" \"f\":");
208 | sb.append('"');
209 | sb.append(f);
210 | sb.append('"');
211 | sb.append(",\n");
212 |
213 | sb.append(" \"h\":");
214 | sb.append('"');
215 | sb.append(h);
216 | sb.append('"');
217 | sb.append(",\n");
218 |
219 | sb.append(" \"G\":");
220 | sb.append('"');
221 | sb.append(G);
222 | sb.append('"');
223 | sb.append(",\n");
224 |
225 | sb.append(" \"H\":");
226 | sb.append('"');
227 | sb.append(H);
228 | sb.append('"');
229 | sb.append(",\n");
230 |
231 | sb.append(" \"f_j\":");
232 | sb.append(Lw14Util.toString(f_j, 4, 4));
233 | sb.append(",\n");
234 |
235 | sb.append(" \"E_i\":");
236 | sb.append(Lw14Util.toString(E_i, 4, 4));
237 | sb.append(",\n");
238 |
239 | sb.append(" \"G_i\":");
240 | sb.append(Lw14Util.toString(G_i, 4, 4));
241 | sb.append(",\n");
242 |
243 | sb.append(" \"Z_i\":");
244 | sb.append(Lw14Util.toString(Z_i, 4, 4));
245 | sb.append(",\n");
246 |
247 | sb.append(" \"H_j\":");
248 | sb.append(Lw14Util.toString(H_j, 4, 4));
249 |
250 | sb.append("\n}");
251 | return sb.toString();
252 | }
253 |
254 | public static int getSerializeVersion() {
255 | return SERIALIZE_VERSION;
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeSecretMasterKey.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.OutputStream;
10 | import java.util.Arrays;
11 |
12 | import it.unisa.dia.gas.jpbc.Element;
13 | import trabe.lw14.Lw14Util;
14 |
15 | /**
16 | * A master secret key
17 | */
18 | public class AbeSecretMasterKey {
19 |
20 | private static final int SERIALIZE_VERSION = 1;
21 |
22 | private final AbePublicKey pubKey;
23 | /** [Zr] **/
24 | public final Element[] alpha_i;
25 | /** [Zr] **/
26 | public final Element[] r_i;
27 | /** [Zr] **/
28 | public final Element[] c_j;
29 |
30 | public final Element b;
31 |
32 | public int counter;
33 |
34 | public AbePublicKey getPublicKey() {
35 | return pubKey;
36 | }
37 |
38 | public int getMaxUsers() {
39 | return getSqrtUsers() * getSqrtUsers() - 1;
40 | }
41 |
42 | public AbeSecretMasterKey(AbePublicKey pubKey, Element[] alpha_i, Element[] r_i, Element[] c_j, Element b) {
43 | this(pubKey, alpha_i, r_i, c_j, b, 0);
44 | }
45 |
46 | public AbeSecretMasterKey(AbePublicKey pubKey, Element[] alpha_i, Element[] r_i, Element[] c_j, Element b, int counter) {
47 | this.pubKey = pubKey;
48 | this.alpha_i = alpha_i;
49 | this.r_i = r_i;
50 | this.c_j = c_j;
51 | this.b = b;
52 | this.counter = counter;
53 | }
54 |
55 | private static AbeSecretMasterKey readFromStream(AbeInputStream stream) throws IOException {
56 | int version = stream.readInt();
57 |
58 | AbePublicKey pubKey = AbePublicKey.readFromStream(stream);
59 | //stream.setPublicKey(pubKey);
60 |
61 | int usersSqrt = stream.readInt();
62 | int counter = stream.readInt();
63 |
64 | Element[] alpha_i = Lw14Util.readElementArray(usersSqrt, stream);
65 | Element[] r_i = Lw14Util.readElementArray(usersSqrt, stream);
66 | Element[] c_j = Lw14Util.readElementArray(usersSqrt, stream);
67 |
68 | return new AbeSecretMasterKey(pubKey, alpha_i, r_i, c_j, null, counter);
69 | }
70 |
71 | public static AbeSecretMasterKey readFromFile(File file) throws IOException {
72 | AbeInputStream stream = new AbeInputStream(new FileInputStream(file));
73 | try {
74 | return readFromStream(stream);
75 | } finally {
76 | stream.close();
77 | }
78 | }
79 |
80 | public static AbeSecretMasterKey readFromByteArray(byte[] data) throws IOException {
81 | AbeInputStream stream = new AbeInputStream(new ByteArrayInputStream(data));
82 | try {
83 | return readFromStream(stream);
84 | } finally {
85 | stream.close();
86 | }
87 | }
88 |
89 | public void writeToFile(File file) throws IOException {
90 | AbeOutputStream fileStream = new AbeOutputStream(new FileOutputStream(file), pubKey);
91 | writeToStream(fileStream);
92 | fileStream.flush();
93 | fileStream.close();
94 | }
95 |
96 | public void writeToStream(OutputStream stream) throws IOException {
97 | writeToStream(new AbeOutputStream(stream, pubKey));
98 | }
99 |
100 | public void writeToStream(AbeOutputStream stream) throws IOException {
101 | stream.writeInt(SERIALIZE_VERSION);
102 |
103 | pubKey.writeToStream(stream);
104 |
105 | stream.writeInt(getSqrtUsers());
106 | stream.writeInt(counter);
107 |
108 | Lw14Util.writeArray(alpha_i, stream, false);
109 | Lw14Util.writeArray(r_i, stream, false);
110 | Lw14Util.writeArray(c_j, stream, false);
111 | }
112 |
113 | public byte[] getAsByteArray() throws IOException {
114 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
115 | this.writeToStream(baos);
116 | return baos.toByteArray();
117 | }
118 |
119 | public int getSqrtUsers(){
120 | return this.c_j.length;
121 | }
122 |
123 | public AbeUserIndex getCurrentPosition(){
124 | return new AbeUserIndex(getSqrtUsers(), counter);
125 | }
126 |
127 | @Override
128 | public boolean equals(Object obj) {
129 | if (obj == null || !(obj instanceof AbeSecretMasterKey)) {
130 | return false;
131 | } else if(this == obj) {
132 | return true;
133 | }
134 | AbeSecretMasterKey msk = (AbeSecretMasterKey)obj;
135 |
136 | boolean result = pubKey.equals(msk.pubKey);
137 | result = result && Arrays.equals(alpha_i, msk.alpha_i);
138 | result = result && Arrays.equals(r_i, msk.r_i);
139 | result = result && Arrays.equals(c_j, msk.c_j);
140 | result = result && counter == msk.counter;
141 |
142 | return result;
143 | }
144 |
145 | @Override
146 | public String toString() {
147 | StringBuilder sb = new StringBuilder();
148 | sb.append("{\n");
149 |
150 | sb.append(" \"alpha_i\":");
151 | sb.append(Lw14Util.toString(alpha_i, 4, 4));
152 | sb.append(",\n");
153 |
154 | sb.append(" \"r_i\":");
155 | sb.append(Lw14Util.toString(r_i, 4, 4));
156 | sb.append(",\n");
157 |
158 | sb.append(" \"c_j\":");
159 | sb.append(Lw14Util.toString(c_j, 4, 4));
160 | sb.append(",\n");
161 |
162 | sb.append(" \"counter\":");
163 | sb.append(counter);
164 |
165 | sb.append("\n}");
166 | return sb.toString();
167 | }
168 |
169 | public static int getSerializeVersion() {
170 | return SERIALIZE_VERSION;
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeSettings.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | public class AbeSettings {
4 | public final static boolean DEBUG = false;
5 | public final static String STRINGS_LOCALE = "US-ASCII";
6 | public final static String ELEMENT_HASHING_ALGORITHM = "SHA-1";
7 | public final static String curveParams = "type a\n"
8 | + "q 87807107996633125224377819847540498158068831994142082"
9 | + "1102865339926647563088022295707862517942266222142315585"
10 | + "8769582317459277713367317481324925129998224791\n"
11 | + "h 12016012264891146079388821366740534204802954401251311"
12 | + "822919615131047207289359704531102844802183906537786776\n"
13 | + "r 730750818665451621361119245571504901405976559617\n"
14 | + "exp2 159\n" + "exp1 107\n"
15 | + "sign1 1\n" + "sign0 1\n";
16 | public final static boolean USE_TREE = true; // otherwise LSSS matrix
17 |
18 | public static boolean PREPROCESSING = true;
19 | public static int PREPROCESSING_THRESHOLD = 6; // how many exponentiations with the same basis are needed for pre-processing to make sense
20 |
21 | // currently broken:
22 | public final static boolean USE_THRESHOLD_MATRIX = false; // otherwise LSSS matrix from boolean formula
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/trabe/AbeUserIndex.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | /**
4 | * Defines a position in a matrix starting with (0,0) and ending with (m-1,m-1).
5 | * It relies on the counter and matrix side length according to the formula:
6 | * i * m + j = ctr - 1
.
7 | * */
8 | public class AbeUserIndex {
9 | public final int i;
10 | public final int j;
11 |
12 | public final int counter;
13 | public final int m;
14 |
15 | public AbeUserIndex(int matrixLength, int counter){
16 | this.i = counter / matrixLength;
17 | this.j = counter % matrixLength;
18 | this.counter = counter;
19 | this.m = matrixLength;
20 | }
21 |
22 | public AbeUserIndex(int i, int j, int matrixLength){
23 | this.i = i;
24 | this.j = j;
25 | this.counter = i * matrixLength + j;
26 | this.m = matrixLength;
27 | }
28 |
29 | @Override
30 | public boolean equals(Object obj) {
31 | if (obj == null || !(obj instanceof AbeUserIndex)) {
32 | return false;
33 | } else if(this == obj) {
34 | return true;
35 | }
36 | AbeUserIndex index = (AbeUserIndex)obj;
37 |
38 | boolean result = i == index.i;
39 | result = result && j == index.j;
40 | result = result && counter == index.counter;
41 | result = result && m == index.m;
42 |
43 | return result;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/trabe/CpabeWeber.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
4 |
5 | import java.io.BufferedInputStream;
6 | import java.io.BufferedOutputStream;
7 | import java.io.ByteArrayInputStream;
8 | import java.io.ByteArrayOutputStream;
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.FileOutputStream;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.io.OutputStream;
15 |
16 | import trabe.lw14.Lw14;
17 | import trabe.policyparser.ParseException;
18 |
19 | public class CpabeWeber {
20 | static {
21 | try {
22 | System.loadLibrary("jpbc-pbc");
23 | } catch (UnsatisfiedLinkError e) {
24 | // cant fix this error, jcpabe still runs (slowly)
25 | }
26 | PairingFactory.getInstance().setUsePBCWhenPossible(true);
27 | }
28 |
29 | public static AbeSecretMasterKey setup() {
30 | return Lw14.setup(16);
31 | }
32 |
33 | public static void setup(File publicMasterFile, File secretMasterFile) throws IOException {
34 | AbeSecretMasterKey masterKey = setup();
35 | masterKey.writeToFile(secretMasterFile);
36 | masterKey.getPublicKey().writeToFile(publicMasterFile);
37 | }
38 |
39 | public static AbePrivateKey keygen(AbeSecretMasterKey secretMaster, String attributes) throws ParseException {
40 | return null;
41 | // String parsedAttributes = AttributeParser.parseAttributes(attributes);
42 | // String[] splitAttributes = parsedAttributes.split(" ");
43 | // return Lw14.keygen(secretMaster, splitAttributes);
44 | }
45 |
46 | public static void keygen(File privateFile, File secretMasterFile, String attributes) throws IOException, ParseException {
47 | AbeSecretMasterKey secretKey = AbeSecretMasterKey.readFromFile(secretMasterFile);
48 | AbePrivateKey prv = keygen(secretKey, attributes);
49 | prv.writeToFile(privateFile);
50 | }
51 |
52 | public static AbePrivateKey delegate(AbePrivateKey oldPrivateKey, String attributeSubset) throws ParseException {
53 | return null;
54 | // String parsedAttributeSubset = AttributeParser.parseAttributes(attributeSubset);
55 | // String[] splitAttributeSubset = parsedAttributeSubset.split(" ");
56 | // return Lw14.delegate(oldPrivateKey, splitAttributeSubset);
57 | }
58 |
59 | public static void delegate(File oldPrivateKeyFile, String attributeSubset, File newPrivateKeyFile) throws IOException, ParseException {
60 | AbePrivateKey oldPrivateKey = AbePrivateKey.readFromFile(oldPrivateKeyFile);
61 | AbePrivateKey newPrivateKey = delegate(oldPrivateKey, attributeSubset);
62 | newPrivateKey.writeToFile(newPrivateKeyFile);
63 | }
64 |
65 | public static void decrypt(AbePrivateKey privateKey, InputStream input, OutputStream output, byte[] lbeKey) throws IOException, AbeDecryptionException {
66 | AbeEncrypted encrypted = AbeEncrypted.readFromStream(privateKey.getPublicKey(), input);
67 | encrypted.writeDecryptedData(privateKey, lbeKey, output);
68 | }
69 |
70 | public static byte[] decrypt(AbePrivateKey privateKey, AbeEncrypted encryptedData, byte[] lbeKey) throws AbeDecryptionException, IOException {
71 | ByteArrayOutputStream out = new ByteArrayOutputStream();
72 | encryptedData.writeDecryptedData(privateKey, lbeKey, out);
73 | return out.toByteArray();
74 | }
75 |
76 | public static void decrypt(File privateKeyFile, File encryptedFile, File decryptedFile, byte[] lbeKey) throws IOException, AbeDecryptionException {
77 | AbePrivateKey privateKey = AbePrivateKey.readFromFile(privateKeyFile);
78 | BufferedInputStream in = null;
79 | BufferedOutputStream out = null;
80 | try {
81 | in = new BufferedInputStream(new FileInputStream(encryptedFile));
82 | out = new BufferedOutputStream(new FileOutputStream(decryptedFile));
83 | decrypt(privateKey, in, out, lbeKey);
84 | } finally {
85 | if (out != null)
86 | out.close();
87 | if (in != null)
88 | in.close();
89 | }
90 | }
91 |
92 | public static void encrypt(AbePublicKey publicKey, String policy, InputStream input, OutputStream output, byte[] lbeKey) throws AbeEncryptionException, IOException {
93 | AbeEncrypted encrypted = encrypt(publicKey, policy, input, lbeKey);
94 | encrypted.writeEncryptedFile(output, publicKey);
95 | }
96 |
97 | public static AbeEncrypted encrypt(AbePublicKey publicKey, String policy, InputStream input, byte[] lbeKey) throws AbeEncryptionException, IOException {
98 | /*try {
99 | String parsedPolicy = PolicyParsing.parsePolicy(policy);
100 | Bsw07CipherAndKey cipherAndKey = Lw14.encrypt(publicKey, parsedPolicy);
101 | Bsw07Cipher abeEncryptedSecret = cipherAndKey.getCipher();
102 | Element plainSecret = cipherAndKey.getKey();
103 |
104 | if (abeEncryptedSecret == null) {
105 | throw new AbeEncryptionException("ABE Encryption failed");
106 | }
107 |
108 | byte[] iv = new byte[16];
109 | SecureRandom random = new SecureRandom();
110 | random.nextBytes(iv);
111 | return AbeEncrypted.createDuringEncryption(iv, lbeKey, abeEncryptedSecret, input, plainSecret);
112 | } catch (ParseException e) {
113 | throw new AbeEncryptionException("error while parsing policy", e);
114 | }*/
115 | return null;
116 | }
117 |
118 | public static AbeEncrypted encrypt(AbePublicKey publicKey, String policy, byte[] data, byte[] lbeKey) throws AbeEncryptionException, IOException {
119 | ByteArrayInputStream byteIn = new ByteArrayInputStream(data);
120 | return encrypt(publicKey, policy, byteIn, lbeKey);
121 | }
122 |
123 | public static void encrypt(File publicKeyFile, String policy, File inputFile, File outputFile, byte[] lbeKey) throws IOException, AbeEncryptionException {
124 | AbePublicKey publicKey = AbePublicKey.readFromFile(publicKeyFile);
125 | BufferedInputStream in = null;
126 | BufferedOutputStream out = null;
127 | try {
128 | in = new BufferedInputStream(new FileInputStream(inputFile));
129 | out = new BufferedOutputStream(new FileOutputStream(outputFile));
130 | encrypt(publicKey, policy, in, out, lbeKey);
131 | } finally {
132 | if (out != null)
133 | out.close();
134 | if (in != null)
135 | in.close();
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/main/java/trabe/DecryptionBlackBox.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | /**
4 | * The decryption black box may consist of multiple keys from different users
5 | * which makes up a whole. It may act probabilistically and decrypt ciphertexts
6 | * which use some but not all attributes of the users that the black box was
7 | * built from.
8 | */
9 | public abstract class DecryptionBlackBox {
10 |
11 | /**
12 | * Determine if the given cipher text can be decrypted using this black box.
13 | * @param ct Cipher text
14 | * @return is decryptable
15 | */
16 | public boolean canDecrypt(AbeEncrypted ct) {
17 | byte[] pt = decrypt(ct);
18 | return pt != null;
19 | }
20 |
21 | /**
22 | * Determine if the given cipher text can be decrypted using this black box.
23 | * @param ct Cipher text
24 | * @return plaintext
25 | */
26 | public abstract byte[] decrypt(AbeEncrypted ct);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/trabe/DecryptionException.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import java.security.GeneralSecurityException;
4 |
5 | public class DecryptionException extends GeneralSecurityException {
6 |
7 | private static final long serialVersionUID = 2848983353356953397L;
8 |
9 | public DecryptionException() {
10 | super();
11 | }
12 |
13 | public DecryptionException(String msg) {
14 | super(msg);
15 | }
16 |
17 | public DecryptionException(Throwable t) {
18 | super(t);
19 | }
20 |
21 | public DecryptionException(String msg, Throwable t) {
22 | super(msg, t);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/trabe/ElementVector.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import it.unisa.dia.gas.jpbc.*;
4 | import trabe.lw14.Lw14Util;
5 | import trabe.lw14.policy.LsssMatrix;
6 |
7 | import java.io.IOException;
8 |
9 | public class ElementVector {
10 | private int dimension;
11 | private Element[] vector;
12 |
13 | public ElementVector(Element[] vector) {
14 | this.dimension = vector.length;
15 | this.vector = vector;
16 | }
17 |
18 | /**
19 | * Initialize vector from matrix row.
20 | * @param vector Integer vector
21 | * @param zr Zr group identifier
22 | */
23 | public ElementVector(int[] vector, Field zr) {
24 | dimension = vector.length;
25 | this.vector = new Element[dimension];
26 | for(int i = 0; i < dimension; i++) {
27 | this.vector[i] = zr.newElement(vector[i]);
28 | }
29 | }
30 |
31 | /**
32 | * Initialize a three dimensional vector.
33 | * @param x1 Element 1
34 | * @param x2 Element 2
35 | * @param x3 Element 3
36 | */
37 | public ElementVector(Element x1, Element x2, Element x3){
38 | this.dimension = 3;
39 | this.vector = new Element[]{x1, x2, x3};
40 | }
41 |
42 | /**
43 | * Create a vector.
44 | * @param dimension Dimension of the intended vector
45 | */
46 | public ElementVector(int dimension){
47 | this.dimension = dimension;
48 | this.vector = new Element[dimension];
49 | }
50 |
51 | /**
52 | * Initialize a vector with the same element.
53 | * @param dimension Dimension of the intended vector
54 | * @param e Element that is set to all components
55 | */
56 | public ElementVector(int dimension, Element e){
57 | this.dimension = dimension;
58 | this.vector = new Element[dimension];
59 | for(int i = 0; i < dimension; i++){
60 | this.vector[i] = e.duplicate();
61 | }
62 | }
63 |
64 | /**
65 | * Create a three dimensional vector.
66 | */
67 | public ElementVector(){
68 | this(3);
69 | }
70 |
71 | /**
72 | * Initialize a random three-dimensional vector.
73 | * @param field Field type where the random elements should be in
74 | */
75 | public ElementVector(Field field){
76 | this(3, field);
77 | }
78 |
79 | /**
80 | * Initialize a random vector.
81 | * @param dimension Dimension of the intended vector
82 | * @param field Field type where the random elements should be in
83 | */
84 | public ElementVector(int dimension, Field field){
85 | this.dimension = dimension;
86 | this.vector = new Element[dimension];
87 | for(int i = 0; i < dimension; i++){
88 | this.vector[i] = field.newRandomElement();
89 | }
90 | }
91 |
92 | public int getDimension(){
93 | return dimension;
94 | }
95 |
96 | public Element get(int i){
97 | return vector[i];
98 | }
99 |
100 | public void set(int i, Element x){
101 | vector[i] = x;
102 | }
103 |
104 | /**
105 | * Operations on vectors run on the vector itself, so a copy is needed.
106 | * @return Copy of the vector
107 | */
108 | public ElementVector duplicate(){
109 | Element[] newVector = new Element[dimension];
110 | for(int i = 0; i < dimension; i++){
111 | newVector[i] = vector[i].duplicate();
112 | }
113 | return new ElementVector(newVector);
114 | }
115 |
116 | /**
117 | * Multiply two vectors to get a changed vector. The original vector will be overwritten.
118 | * Use duplicate()
to get a copy.
119 | *
120 | * @param v Second vector
121 | * @return this
122 | */
123 | public ElementVector mul(ElementVector v) {
124 | if (dimension != v.getDimension()) {
125 | return null;
126 | }
127 | for(int i = 0; i < dimension; i++){
128 | vector[i].mul(v.get(i));
129 | }
130 | return this;
131 | }
132 |
133 | /**
134 | * Multiply the current vector with a scalar and return it. The original vector will be overwritten.
135 | * Use duplicate()
to get a copy.
136 | * @param e Element to multiply with
137 | * @return this
138 | */
139 | public ElementVector mul(Element e) {
140 | for(int i = 0; i < dimension; i++){
141 | vector[i].mul(e);
142 | }
143 | return this;
144 | }
145 |
146 | /**
147 | * Computes the scalar product between two vectors. Duplicating is not necessary.
148 | *
149 | * @param v Second vector
150 | * @return Product
151 | */
152 | public Element scalar(ElementVector v) {
153 | return duplicate().mul(v).sum();
154 | }
155 |
156 | /**
157 | * Sums all of the components of the vector into a single element. Duplication is not necessary.
158 | * @return Sum of components
159 | */
160 | public Element sum(){
161 | Element result = vector[0].duplicate();
162 | for(int i = 1; i < dimension; i++){
163 | result.add(vector[i]);
164 | }
165 | return result;
166 | }
167 |
168 | /**
169 | * Adds all the components of the second vector to the current vector. Duplication might be necessary.
170 | * @param v Second vector
171 | * @return this
172 | */
173 | public ElementVector add(ElementVector v) {
174 | if (dimension != v.getDimension()) {
175 | return null;
176 | }
177 | for(int i = 0; i < dimension; i++){
178 | vector[i].add(v.get(i));
179 | }
180 | return this;
181 | }
182 |
183 | /**
184 | * Raises the passed base element to each of the current vector's components
185 | * to produce a new vector. Duplication is not necessary. The base vector
186 | * will not be manipulated.
187 | * @param base Base for each component
188 | * @return New vector
189 | */
190 | public ElementVector powInBase(ElementPowPreProcessing base) {
191 | Element[] newVector = new Element[dimension];
192 | for(int i = 0; i < dimension; i++){
193 | newVector[i] = base.powZn(vector[i]);
194 | }
195 | return new ElementVector(newVector);
196 | }
197 |
198 | /**
199 | * Raises the passed base element to each of the current vector's components
200 | * to produce a new vector. Duplication is not necessary. The base vector
201 | * will not be manipulated.
202 | * @param base Base for each component
203 | * @return New vector
204 | */
205 | public ElementVector powInBase(Element base) {
206 | Element[] newVector = new Element[dimension];
207 | for(int i = 0; i < dimension; i++){
208 | newVector[i] = base.duplicate().powZn(vector[i]);
209 | }
210 | return new ElementVector(newVector);
211 | }
212 |
213 | /**
214 | * Computes the pairing of this vector with the second vector component wise
215 | * and multiplies all the values resulting values in G_T. Duplication is not necessary.
216 | * @param pairing Pairing which contains the parameters for the pairing
217 | * @param vector Second vector
218 | * @return new element
219 | */
220 | public Element newPair(Pairing pairing, ElementVector vector) {
221 | if (dimension != vector.getDimension()) {
222 | return null;
223 | }
224 | Element element = pairing.getGT().newOneElement();
225 | for(int i = 0; i < dimension; i++){
226 | element = element.mul(pairing.pairing(this.vector[i], vector.get(i))); // assignment not necessary
227 | }
228 | return element;
229 | }
230 |
231 | public boolean equals(Object v) {
232 | if (this == v) {
233 | return true;
234 | }
235 | if (null == v || !this.getClass().equals(v.getClass())) {
236 | return false;
237 | }
238 | ElementVector ev = (ElementVector)v;
239 | if (dimension != ev.getDimension()) {
240 | return false;
241 | }
242 | for(int i = 0; i < dimension; i++) {
243 | if ((vector[i] != null && ev.get(i) == null) || (vector[i] == null && ev.get(i) != null) || !vector[i].isEqual(ev.get(i))) {
244 | return false;
245 | }
246 | }
247 | return true;
248 | }
249 |
250 | public String toString(){
251 | String separator = ", ";
252 | StringBuilder builder = new StringBuilder();
253 | builder.append("V[");
254 | for (int i = 0, il = dimension; i < il; i++) {
255 | if (i > 0) {
256 | builder.append(separator);
257 | }
258 | builder.append(vector[i]);
259 | }
260 | builder.append("]");
261 | return builder.toString();
262 | }
263 |
264 | public static ElementVector createFrom(LsssMatrix matrix, int row, Field zr) {
265 | return matrix.getAttributeRow(row, zr);
266 | }
267 |
268 | public void writeToStream(AbeOutputStream stream) throws IOException {
269 | Lw14Util.writeArray(vector, stream);
270 | }
271 |
272 | public static ElementVector readFromStream(AbeInputStream stream) throws IOException {
273 | return new ElementVector(Lw14Util.readElementArray(stream));
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/src/main/java/trabe/MockBlackBox.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | import trabe.lw14.*;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 |
9 | public class MockBlackBox extends DecryptionBlackBox {
10 |
11 | private List userKeys = new ArrayList();
12 | private AbePublicKey publicKey;
13 |
14 | public MockBlackBox(List userKeys, AbePublicKey publicKey) {
15 | this.userKeys = userKeys;
16 | this.publicKey = publicKey;
17 | }
18 |
19 | public MockBlackBox(AbePrivateKey[] userKeys, AbePublicKey publicKey) {
20 | this.userKeys = new ArrayList(userKeys.length);
21 | Collections.addAll(this.userKeys, userKeys);
22 | this.publicKey = publicKey;
23 | }
24 |
25 | /**
26 | * Determine if the given cipher text can be decrypted using this black box.
27 | *
28 | * @param ct Cipher text
29 | * @return plaintext
30 | */
31 | @Override
32 | public byte[] decrypt(AbeEncrypted ct) {
33 | for(AbePrivateKey key : userKeys) {
34 | try {
35 | String privKeyAttrs = "";
36 | for (String privKeyAttr : key.getAttributeSet()) {
37 | privKeyAttrs += privKeyAttr + " ";
38 | }
39 | if (Lw14.canDecrypt(key, ct.getCipher())) {
40 | System.out.println(privKeyAttrs + " [" + key.position.counter + "] [" + key.position.i + " , "+ key.position.j + "] can decrypt policy: " + ct.getCipher().policy);
41 | return Cpabe.decrypt(key, ct);
42 | }
43 | } catch (Exception ignored) {
44 | }
45 | }
46 | return null;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/trabe/Pair.java:
--------------------------------------------------------------------------------
1 | package trabe;
2 |
3 | /*
4 | * Pair implementation by arturh
5 | * http://stackoverflow.com/questions/156275/what-is-the-equivalent-of-the-c-pairl-r-in-java/677248#677248
6 | * */
7 | public class Pair {
8 | private A first;
9 | private B second;
10 |
11 | public Pair(A first, B second) {
12 | super();
13 | this.first = first;
14 | this.second = second;
15 | }
16 |
17 | public int hashCode() {
18 | int hashFirst = first != null ? first.hashCode() : 0;
19 | int hashSecond = second != null ? second.hashCode() : 0;
20 |
21 | return (hashFirst + hashSecond) * hashSecond + hashFirst;
22 | }
23 |
24 | public boolean equals(Object other) {
25 | if (other instanceof Pair) {
26 | Pair otherPair = (Pair) other;
27 | return
28 | (( this.first == otherPair.first ||
29 | ( this.first != null && otherPair.first != null &&
30 | this.first.equals(otherPair.first))) &&
31 | ( this.second == otherPair.second ||
32 | ( this.second != null && otherPair.second != null &&
33 | this.second.equals(otherPair.second))) );
34 | }
35 |
36 | return false;
37 | }
38 |
39 | public String toString()
40 | {
41 | return "(" + first + ", " + second + ")";
42 | }
43 |
44 | public A getFirst() {
45 | return first;
46 | }
47 |
48 | public void setFirst(A first) {
49 | this.first = first;
50 | }
51 |
52 | public B getSecond() {
53 | return second;
54 | }
55 |
56 | public void setSecond(B second) {
57 | this.second = second;
58 | }
59 | }
--------------------------------------------------------------------------------
/src/main/java/trabe/aes/AesDecryptionException.java:
--------------------------------------------------------------------------------
1 | package trabe.aes;
2 |
3 | import trabe.DecryptionException;
4 |
5 | public class AesDecryptionException extends DecryptionException {
6 | public AesDecryptionException(Throwable throwable) {
7 | super(throwable);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/trabe/aes/AesEncryption.java:
--------------------------------------------------------------------------------
1 | package trabe.aes;
2 |
3 | import java.io.*;
4 | import java.security.GeneralSecurityException;
5 | import java.security.MessageDigest;
6 | import java.security.NoSuchAlgorithmException;
7 | import java.util.Arrays;
8 |
9 | import javax.crypto.Cipher;
10 | import javax.crypto.CipherInputStream;
11 | import javax.crypto.spec.IvParameterSpec;
12 | import javax.crypto.spec.SecretKeySpec;
13 |
14 | import trabe.AbeDecryptionException;
15 | import trabe.AbeEncryptionException;
16 |
17 | public class AesEncryption {
18 | private final static String KEY_ALGORITHM = "AES";
19 | private final static String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; //"AES/GCM/NoPadding" not working on android
20 | private final static String HASHING_ALGORITHM = "SHA-256";
21 | private static final int BUFFERSIZE = 1024;
22 | // We use AES128 per schneier, so we need to reduce the keysize
23 | private static final int AES_KEY_LENGTH = 16;
24 |
25 | static {
26 | //Security.addProvider(new BouncyCastleProvider());
27 | }
28 |
29 | private static byte[] hash(byte[] cpabeData) {
30 | try {
31 | MessageDigest sha256 = MessageDigest.getInstance(HASHING_ALGORITHM);
32 | return Arrays.copyOf(sha256.digest(cpabeData), AES_KEY_LENGTH);
33 | } catch (NoSuchAlgorithmException e) {
34 | e.printStackTrace();
35 | System.err.println(HASHING_ALGORITHM + " not provided by runtime environment. Exiting...");
36 | System.exit(1);
37 | }
38 | return null;
39 | }
40 |
41 | private static byte[] combine(byte[] cpabeData, byte[] lbeKey) {
42 | byte[] hashedCpabeSecret = hash(cpabeData);
43 | if (lbeKey != null) {
44 | if (hashedCpabeSecret.length != lbeKey.length) {
45 | throw new RuntimeException("wrong key size for lbeKey, " + hashedCpabeSecret.length + " bytes required");
46 | }
47 | for (int i = 0; i < lbeKey.length; i++) {
48 | hashedCpabeSecret[i] = (byte) (hashedCpabeSecret[i] ^ lbeKey[i]);
49 | }
50 | }
51 | return hashedCpabeSecret;
52 | }
53 |
54 | public static void encrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv, InputStream input, OutputStream output) throws IOException, AbeEncryptionException {
55 | try {
56 | CipherInputStream cis = encrypt(cpabeKey, lbeKey, iv, input);
57 | int read;
58 | byte[] buffer = new byte[BUFFERSIZE];
59 | while ((read = cis.read(buffer)) >= 0) {
60 | output.write(buffer, 0, read);
61 | }
62 | output.close();
63 | cis.close();
64 | } catch (GeneralSecurityException e) {
65 | throw new AbeEncryptionException(e.getMessage(), e);
66 | }
67 | }
68 |
69 | public static byte[] encrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv, byte[] data) throws IOException, AbeEncryptionException {
70 | ByteArrayInputStream bais = new ByteArrayInputStream(data);
71 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
72 | encrypt(cpabeKey, lbeKey, iv, bais, baos);
73 | return baos.toByteArray();
74 | }
75 |
76 | public static CipherInputStream encrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv, InputStream input) throws IOException, AbeEncryptionException {
77 | try {
78 | SecretKeySpec skeySpec = new SecretKeySpec(combine(cpabeKey, lbeKey), KEY_ALGORITHM);
79 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
80 | cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));
81 | CipherInputStream cis = new CipherInputStream(input, cipher);
82 | return cis;
83 | } catch (GeneralSecurityException e) {
84 | throw new AbeEncryptionException(e.getMessage(), e);
85 | }
86 | }
87 |
88 | public static CipherInputStream decrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv, InputStream input) throws IOException, AbeDecryptionException {
89 | try {
90 | SecretKeySpec skeySpec = new SecretKeySpec(combine(cpabeKey, lbeKey), KEY_ALGORITHM);
91 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
92 | cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));
93 | return new CipherInputStream(input, cipher);
94 | } catch (GeneralSecurityException e) {
95 | throw new AbeDecryptionException(e.getMessage(), e);
96 | }
97 | }
98 |
99 | public static Cipher decrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv) throws IOException {
100 | try {
101 | SecretKeySpec skeySpec = new SecretKeySpec(combine(cpabeKey, lbeKey), KEY_ALGORITHM);
102 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
103 | cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));
104 | return cipher;
105 | } catch (GeneralSecurityException e) {
106 | throw new RuntimeException(e);
107 | }
108 | }
109 |
110 | public static void decrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv, InputStream input, OutputStream output) throws IOException, AesDecryptionException {
111 | Cipher cipher = decrypt(cpabeKey, lbeKey, iv);
112 | int read;
113 | byte[] buffer = new byte[BUFFERSIZE];
114 | while ((read = input.read(buffer)) >= 0) {
115 | byte[] dec = cipher.update(buffer, 0, read);
116 | output.write(dec);
117 | }
118 | try {
119 | byte[] dec = cipher.doFinal();
120 | output.write(dec);
121 | } catch (Exception e) {
122 | throw new AesDecryptionException(e);
123 | }
124 | }
125 |
126 | public static byte[] decrypt(byte[] cpabeKey, byte[] lbeKey, byte[] iv, byte[] data) throws IOException, AesDecryptionException {
127 | ByteArrayInputStream bais = new ByteArrayInputStream(data);
128 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
129 | decrypt(cpabeKey, lbeKey, iv, bais, baos);
130 | return baos.toByteArray();
131 | }
132 | }
--------------------------------------------------------------------------------
/src/main/java/trabe/aes/InputStreamStopper.java:
--------------------------------------------------------------------------------
1 | package trabe.aes;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 |
6 | /**
7 | * Returns EOF after the specified number of bytes has been read. Underlying stream may still have more data.
8 | * Not thread-safe
9 | *
10 | */
11 | public class InputStreamStopper extends InputStream {
12 | private static final int EOF = -1;
13 | private long maxLength;
14 | private long curPos;
15 | private InputStream in;
16 | private static long MAX_READ_PER_CALL = 8192;
17 |
18 | public InputStreamStopper(InputStream in, long maxLength) {
19 | this.curPos = 0;
20 | this.maxLength = maxLength;
21 | this.in = in;
22 | }
23 |
24 | @Override
25 | public int read(byte[] b, int off, int len) throws IOException {
26 | if (curPos >= maxLength) return EOF;
27 | int maxRead = (int) Math.min(Math.min(len, maxLength - curPos), MAX_READ_PER_CALL);
28 | int actualRead = in.read(b, off, maxRead);
29 | if (actualRead != EOF) {
30 | curPos += actualRead;
31 | }
32 | return actualRead;
33 | }
34 |
35 | @Override
36 | public int read() throws IOException {
37 | if (curPos >= maxLength) return EOF;
38 | int val = in.read();
39 | if (val != EOF) {
40 | curPos++;
41 | }
42 | return val;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/Benchmark.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | public abstract class Benchmark {
4 | /**
5 | * Is called once before the benchmark starts.
6 | * Is not timed.
7 | */
8 | public void initializeBenchmark() {
9 |
10 | }
11 |
12 | /**
13 | * Is called at the start of every iteration, but not at the start of every run.
14 | * Is not timed.
15 | * @param iteration Number of iterations to run the benchmark
16 | */
17 | public void initializeIteration(int iteration) {
18 |
19 | }
20 |
21 |
22 | /**
23 | * Is called exactly numWarmupRuns() + numBenchmarkRuns() * numRunsPerRun() times.
24 | * @param iteration the current iteration, begins at 0, also 0 for warmup
25 | */
26 | public abstract void singleRun(int iteration);
27 |
28 | public void destroyIteration(int iteration) {
29 |
30 | }
31 |
32 | public void destroyBenchmark() {
33 |
34 | }
35 |
36 | /**
37 | * How many times should the singleRun be started, before being timed? see warm up related to java
38 | * @return Expected number of warmup runs
39 | */
40 | public abstract int numWarmupRuns();
41 |
42 | /**
43 | * The number of iterations in this benchmark. During each iteration the singleRun method is called numRunsPerIteration times.
44 | * @return Expected number of iterations
45 | */
46 | public abstract int numIterations();
47 |
48 | /**
49 | * The number of runs of singleRun per iteration.
50 | * @return Expected number of runs per iteration
51 | */
52 | public abstract int numRunsPerIteration();
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/BenchmarkResult.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | public class BenchmarkResult {
4 | private double[] averagedResults;
5 | private int current;
6 |
7 | public BenchmarkResult(int testRuns) {
8 | averagedResults = new double[testRuns];
9 | current = 0;
10 | }
11 |
12 | public void addResult(double averageTime) {
13 | averagedResults[current++] = averageTime;
14 | }
15 |
16 | public boolean isFull() {
17 | return current == averagedResults.length;
18 | }
19 |
20 | public double[] getAveragedResults() {
21 | return averagedResults;
22 | }
23 |
24 | public double getAverageTime(){
25 | double avg = 0.0;
26 | for (int i = 0; i < averagedResults.length; i++) {
27 | avg += averagedResults[i];
28 | }
29 | return avg / averagedResults.length;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | // is directly usable in pgfplots
35 | StringBuilder table = new StringBuilder();
36 | table.append("iteration avgtime\n");
37 | for (int i = 0; i < averagedResults.length; i++) {
38 | table.append(i + 1);
39 | table.append(' ');
40 | table.append(averagedResults[i] / 1E9);
41 | table.append('\n');
42 | }
43 | table.append("Overall average: ");
44 | table.append(getAverageTime() / 1E9);
45 | table.append('\n');
46 | return table.toString();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/BenchmarkRunner.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.File;
5 | import java.io.FileWriter;
6 | import java.io.IOException;
7 | import java.io.PrintWriter;
8 |
9 | public class BenchmarkRunner {
10 |
11 | public static void main(String[] args) throws IOException {
12 | runBenchmark(new CpabeKeygenAttributeNumberTest(), new File("bench_CpabeKeygenAttributeNumberTest.log"));
13 | runBenchmark(new CpabeEncryptionAttributeNumberTest(), new File("bench_CpabeEncryptionAttributeNumberTest.log"));
14 | runBenchmark(new CpabeKeygenAttributeNumberTest(), new File("bench_CpabeKeygenAttributeNumberTest_2.log"));
15 | runBenchmark(new CpabeDecryptionOrAttributeNumberTest(), new File("bench_CpabeDecryptionOrAttributeNumberTest.log"));
16 | runBenchmark(new CpabeDecryptionAndAttributeNumberTest(), new File("bench_CpabeDecryptionAndAttributeNumberTest.log"));
17 | }
18 |
19 | public static BenchmarkResult runBenchmark(Benchmark benchmark) {
20 | if (!verifyOptions(benchmark)) return null;
21 |
22 | benchmark.initializeBenchmark();
23 | int warmupRuns = benchmark.numWarmupRuns();
24 | benchmark.initializeIteration(0);
25 | for (int i = 0; i < warmupRuns; i++) {
26 | benchmark.singleRun(0);
27 | }
28 | benchmark.destroyIteration(0);
29 |
30 | int testRuns = benchmark.numIterations();
31 | int runsPerRun = benchmark.numRunsPerIteration();
32 | BenchmarkResult result = new BenchmarkResult(testRuns);
33 |
34 | for (int iteration = 0; iteration < testRuns; iteration++) {
35 | benchmark.initializeIteration(iteration);
36 | long start = System.nanoTime();
37 | for (int i = 0; i < runsPerRun; i++) {
38 | benchmark.singleRun(iteration);
39 | }
40 | long end = System.nanoTime();
41 | double average = (end - start) / (double) runsPerRun;
42 | benchmark.destroyIteration(iteration);
43 | result.addResult(average);
44 | }
45 | benchmark.destroyBenchmark();
46 | return result;
47 | }
48 |
49 | public static BenchmarkResult runBenchmark(Benchmark benchmark, File output) throws IOException {
50 | BenchmarkResult result = runBenchmark(benchmark);
51 | PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(output)));
52 | writer.write(result.toString());
53 | writer.close();
54 | return result;
55 | }
56 |
57 |
58 | private static boolean verifyOptions(Benchmark benchmark) {
59 | if (benchmark.numRunsPerIteration() <= 0) throw new IllegalArgumentException("numRunsPerRun can't be 0 or lower");
60 | if (benchmark.numWarmupRuns() < 0) throw new IllegalArgumentException("numWarmupRuns can't be lower than 0");
61 | if (benchmark.numIterations() <= 0) throw new IllegalArgumentException("numTestRuns can't be 0 or lower");
62 | return true;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/CpabeDecryptionAndAttributeNumberTest.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | import java.util.UUID;
4 |
5 | import trabe.AbeEncrypted;
6 | import trabe.AbeSecretMasterKey;
7 | import trabe.Cpabe;
8 | import trabe.AbePrivateKey;
9 |
10 | public class CpabeDecryptionAndAttributeNumberTest extends Benchmark {
11 |
12 | private byte[] data;
13 |
14 | private AbeSecretMasterKey msk;
15 |
16 | private AbePrivateKey privateKey;
17 | private AbeEncrypted encrypted;
18 |
19 |
20 | @Override
21 | public void initializeIteration(int iteration) {
22 | String[] splitAttributes = new String[iteration + 1]; // at least one
23 |
24 | for (int i = 0; i < splitAttributes.length; i++) {
25 | splitAttributes[i] = "a" + UUID.randomUUID().toString().replace('-', '0'); // policy attribute have to begin with a letter
26 | }
27 |
28 | String policy = splitAttributes[0];
29 | String attributes = splitAttributes[0];
30 | for (int i = 1; i < splitAttributes.length; i++) {
31 | attributes += " " + splitAttributes[i];
32 | policy += " and " + splitAttributes[i];
33 | }
34 |
35 | try {
36 | encrypted = Cpabe.encrypt(msk.getPublicKey(), policy, data);
37 | privateKey = Cpabe.keygenSingle(msk, attributes);
38 | } catch (Exception e) {
39 | throw new RuntimeException("exception thrown iteration initialization", e);
40 | }
41 | }
42 |
43 | @Override
44 | public void singleRun(int iteration) {
45 | try {
46 | if (Cpabe.decrypt(privateKey, encrypted) == null) {
47 | throw new RuntimeException("couldn't recover plaintext");
48 | }
49 | } catch (Exception e) {
50 | throw new RuntimeException("exception thrown during test", e);
51 | }
52 | }
53 |
54 | @Override
55 | public void initializeBenchmark() {
56 | msk = Cpabe.setup(numIterations() * numRunsPerIteration() + numWarmupRuns());
57 |
58 | data = new byte[255]; // not actually relevant, since we dont really encrypt this
59 | for (int i = 0; i < data.length; i++) {
60 | data[i] = (byte) (i % 256);
61 | }
62 | }
63 |
64 | @Override
65 | public int numWarmupRuns() {
66 | return 5;
67 | }
68 |
69 | @Override
70 | public int numIterations() {
71 | return 20;
72 | }
73 |
74 | @Override
75 | public int numRunsPerIteration() {
76 | return 5;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/CpabeDecryptionOrAttributeNumberTest.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | import java.util.UUID;
4 |
5 | import trabe.AbeEncrypted;
6 | import trabe.AbeSecretMasterKey;
7 | import trabe.Cpabe;
8 | import trabe.AbePrivateKey;
9 |
10 | public class CpabeDecryptionOrAttributeNumberTest extends Benchmark {
11 |
12 | private byte[] data;
13 |
14 | private AbeSecretMasterKey msk;
15 |
16 | private AbePrivateKey privateKey;
17 | private AbeEncrypted encrypted;
18 |
19 |
20 | @Override
21 | public void initializeIteration(int iteration) {
22 | String[] splitAttributes = new String[iteration + 1]; // at least one
23 |
24 | for (int i = 0; i < splitAttributes.length; i++) {
25 | splitAttributes[i] = "a" + UUID.randomUUID().toString().replace('-', '0'); // policy attribute have to begin with a letter
26 | }
27 |
28 | String policy = splitAttributes[0];
29 | String attributes = splitAttributes[0];
30 | for (int i = 1; i < splitAttributes.length; i++) {
31 | attributes += " " + splitAttributes[i];
32 | policy += " or " + splitAttributes[i];
33 | }
34 |
35 | try {
36 | encrypted = Cpabe.encrypt(msk.getPublicKey(), policy, data);
37 | privateKey = Cpabe.keygenSingle(msk, attributes);
38 | } catch (Exception e) {
39 | throw new RuntimeException("exception thrown iteration initialization", e);
40 | }
41 | }
42 |
43 | @Override
44 | public void singleRun(int iteration) {
45 | try {
46 | if (Cpabe.decrypt(privateKey, encrypted) == null) {
47 | throw new RuntimeException("couldn't recover plaintext");
48 | }
49 | } catch (Exception e) {
50 | throw new RuntimeException("exception thrown during test", e);
51 | }
52 | }
53 |
54 | @Override
55 | public void initializeBenchmark() {
56 | msk = Cpabe.setup(numIterations() * numRunsPerIteration() + numWarmupRuns());
57 |
58 | data = new byte[255]; // not actually relevant, since we dont really encrypt this
59 | for (int i = 0; i < data.length; i++) {
60 | data[i] = (byte) (i % 256);
61 | }
62 | }
63 |
64 | @Override
65 | public int numWarmupRuns() {
66 | return 5;
67 | }
68 |
69 | @Override
70 | public int numIterations() {
71 | return 20;
72 | }
73 |
74 | @Override
75 | public int numRunsPerIteration() {
76 | return 5;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/CpabeEncryptionAttributeNumberTest.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | import trabe.AbeSecretMasterKey;
4 | import trabe.Cpabe;
5 |
6 | public class CpabeEncryptionAttributeNumberTest extends Benchmark {
7 |
8 | private byte[] data;
9 |
10 | private AbeSecretMasterKey msk;
11 |
12 | private String policy = "";
13 |
14 |
15 | @Override
16 | public void initializeIteration(int iteration) {
17 | policy = "a";
18 | for (int i = 0; i < iteration; i++) {
19 | policy += " and a";
20 | }
21 | }
22 |
23 | @Override
24 | public void singleRun(int iteration) {
25 | try {
26 | Cpabe.encrypt(msk.getPublicKey(), policy, data); // hope this doesnt get optimized away
27 | } catch (Exception e) {
28 | throw new RuntimeException("exception thrown during test", e);
29 | }
30 | }
31 |
32 | @Override
33 | public void initializeBenchmark() {
34 | msk = Cpabe.setup(numIterations() * numRunsPerIteration() + numWarmupRuns());
35 |
36 | data = new byte[255]; // not actually relevant, since we dont really encrypt this
37 | for (int i = 0; i < data.length; i++) {
38 | data[i] = (byte) (i % 256);
39 | }
40 | }
41 |
42 | @Override
43 | public int numWarmupRuns() {
44 | return 5;
45 | }
46 |
47 | @Override
48 | public int numIterations() {
49 | return 20;
50 | }
51 |
52 | @Override
53 | public int numRunsPerIteration() {
54 | return 5;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/trabe/benchmark/CpabeKeygenAttributeNumberTest.java:
--------------------------------------------------------------------------------
1 | package trabe.benchmark;
2 |
3 | import java.util.UUID;
4 |
5 | import trabe.AbeSecretMasterKey;
6 | import trabe.Cpabe;
7 |
8 | public class CpabeKeygenAttributeNumberTest extends Benchmark {
9 | private AbeSecretMasterKey msk;
10 |
11 | private String attributes = "";
12 |
13 |
14 | @Override
15 | public void initializeIteration(int iteration) {
16 | attributes = UUID.randomUUID().toString();
17 | for (int i = 0; i < iteration; i++) {
18 | attributes += " " + UUID.randomUUID();
19 | }
20 | }
21 |
22 | @Override
23 | public void singleRun(int iteration) {
24 | try {
25 | Cpabe.keygenSingle(msk, attributes);
26 | } catch (Exception e) {
27 | throw new RuntimeException("exception thrown during test", e);
28 | }
29 | }
30 |
31 | @Override
32 | public void initializeBenchmark() {
33 | msk = Cpabe.setup(numIterations() * numRunsPerIteration() + numWarmupRuns());
34 | }
35 |
36 | @Override
37 | public int numWarmupRuns() {
38 | return 5;
39 | }
40 |
41 | @Override
42 | public int numIterations() {
43 | return 10;
44 | }
45 |
46 | @Override
47 | public int numRunsPerIteration() {
48 | return 5;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/trabe/demo/BlackBoxDemo.java:
--------------------------------------------------------------------------------
1 | package trabe.demo;
2 |
3 | import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
4 | import trabe.*;
5 |
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | public class BlackBoxDemo {
10 |
11 | public static void main(String[] args) throws Exception {
12 | AbeSecretMasterKey smKey = Cpabe.setup(2);
13 | AbePublicKey pubKey = smKey.getPublicKey();
14 |
15 | String policy1 = "(att1 and att2) or att3";
16 |
17 | String att1att2att3Attribute = "att1 att2 att3";
18 | String att1att2Attribute = "att1 att2";
19 | String att1att3Attribute = "att1 att3";
20 | String att2att3Attribute = "att2 att3";
21 | String att1Attribute = "att1";
22 | String att2Attribute = "att2";
23 | String att3Attribute = "att3";
24 |
25 | // AbePrivateKey att1att2att3Key = Cpabe.keygenSingle(smKey, att1att2att3Attribute);
26 | AbePrivateKey att1att2Key = Cpabe.keygenSingle(smKey, att1att2Attribute);
27 | // AbePrivateKey att1att3Key = Cpabe.keygenSingle(smKey, att1att3Attribute);
28 | // AbePrivateKey att2att3Key = Cpabe.keygenSingle(smKey, att2att3Attribute);
29 | AbePrivateKey att1Key = Cpabe.keygenSingle(smKey, att1Attribute);
30 | // AbePrivateKey att2Key = Cpabe.keygenSingle(smKey, att2Attribute);
31 | // AbePrivateKey att3Key = Cpabe.keygenSingle(smKey, att3Attribute);
32 |
33 | DecryptionBlackBox bb1 = new MockBlackBox(new AbePrivateKey[]{ att1att2Key, att1Key }, pubKey);
34 | // DecryptionBlackBox bb2 = new MockBlackBox(new AbePrivateKey[]{ att1att2Key }, pubKey);
35 | // DecryptionBlackBox bb3 = new MockBlackBox(new AbePrivateKey[]{ att1Key }, pubKey);
36 |
37 |
38 | long timeStart = System.currentTimeMillis();
39 | List userIndexes;
40 | userIndexes = Cpabe.trace(pubKey, policy1, bb1, 0.9);
41 | assert userIndexes != null;
42 | long timeEnd = System.currentTimeMillis();
43 | System.out.println(String.format("this trace took %d ms.", timeEnd - timeStart));
44 |
45 | System.out.println("Success: " + (userIndexes.size() == 1));
46 | System.out.println("Offending user ids: " + Arrays.toString(userIndexes.toArray()));
47 |
48 | System.out.println("wasPbcAvailable? "+PairingFactory.getInstance().isPBCAvailable());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/trabe/demo/DemoForCpabe.java:
--------------------------------------------------------------------------------
1 | package trabe.demo;
2 |
3 | import java.security.SecureRandom;
4 | import java.util.Arrays;
5 |
6 | import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
7 | import trabe.*;
8 |
9 | public class DemoForCpabe {
10 |
11 | public static void main(String[] args) throws Exception {
12 | long timeStart = System.currentTimeMillis();
13 | AbeSecretMasterKey smKey = Cpabe.setup(4);
14 |
15 | AbePublicKey pubKey = smKey.getPublicKey();
16 |
17 | SecureRandom r = new SecureRandom();
18 | byte[] data = new byte[100];
19 | r.nextBytes(data);
20 |
21 | String policy1 = "(att1 and att2) or att3";
22 | AbeEncrypted ct1 = Cpabe.encrypt(pubKey, policy1, data);
23 |
24 | String att1att2Attribute = "att1 att2";
25 | AbePrivateKey att1att2Key = Cpabe.keygenSingle(smKey, att1att2Attribute);
26 |
27 | System.out.println("Success: " + Arrays.equals(data, Cpabe.decrypt(att1att2Key, ct1)));
28 | long timeEnd = System.currentTimeMillis();
29 |
30 | System.out.println(String.format("this operation took %d ms.", timeEnd - timeStart));
31 | System.out.println("wasPbcAvailable? "+PairingFactory.getInstance().isPBCAvailable());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/CipherText.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import trabe.AbeInputStream;
4 | import trabe.AbeOutputStream;
5 | import trabe.AbePublicKey;
6 | import trabe.ElementVector;
7 | import trabe.lw14.policy.LsssMatrix;
8 | import it.unisa.dia.gas.jpbc.Element;
9 | import trabe.lw14.policy.Lw14PolicyAbstractNode;
10 |
11 | import java.io.ByteArrayInputStream;
12 | import java.io.ByteArrayOutputStream;
13 | import java.io.IOException;
14 | import java.util.Arrays;
15 |
16 | public class CipherText {
17 | private static final int SERIALIZE_VERSION = 1;
18 |
19 | public LsssMatrix accessMatrix = null;
20 | public Lw14PolicyAbstractNode accessTree = null;
21 | /** G_1 **/
22 | public ElementVector[] r1;
23 | /** G_1 **/
24 | public ElementVector[] r2;
25 | /** G_1 **/
26 | public Element[] q1;
27 | /** G_1 **/
28 | public Element[] q2;
29 | /** G_1 **/
30 | public Element[] q3;
31 | /** G_T **/
32 | public Element[] t;
33 | /** G_1 **/
34 | public ElementVector[] c1;
35 | /** G_1 **/
36 | public ElementVector[] c2;
37 | /** G_1 **/
38 | public Element[] p1;
39 | /** G_1 **/
40 | public Element[] p2;
41 | /** G_1 **/
42 | public Element[] p3;
43 | public String policy;
44 |
45 | public int[] revokedUserIndexes;
46 |
47 | private CipherText(){}
48 |
49 | public CipherText(LsssMatrix accessMatrix, ElementVector[] r1, ElementVector[] r2,
50 | Element[] q1, Element[] q2, Element[] q3, Element[] t,
51 | ElementVector[] c1, ElementVector[] c2,
52 | Element[] p1, Element[] p2, Element[] p3,
53 | String policy, int[] revokedUserIndexes) {
54 | this.accessMatrix = accessMatrix;
55 | this.r1 = r1;
56 | this.r2 = r2;
57 | this.q1 = q1;
58 | this.q2 = q2;
59 | this.q3 = q3;
60 | this.t = t;
61 | this.c1 = c1;
62 | this.c2 = c2;
63 | this.p1 = p1;
64 | this.p2 = p2;
65 | this.p3 = p3;
66 | this.policy = policy;
67 | this.revokedUserIndexes = revokedUserIndexes;
68 | }
69 |
70 | public CipherText(Lw14PolicyAbstractNode accessTree, ElementVector[] r1, ElementVector[] r2,
71 | Element[] q1, Element[] q2, Element[] q3, Element[] t,
72 | ElementVector[] c1, ElementVector[] c2,
73 | String policy, int[] revokedUserIndexes) {
74 | this.accessTree = accessTree;
75 | this.r1 = r1;
76 | this.r2 = r2;
77 | this.q1 = q1;
78 | this.q2 = q2;
79 | this.q3 = q3;
80 | this.t = t;
81 | this.c1 = c1;
82 | this.c2 = c2;
83 | this.policy = policy;
84 | this.revokedUserIndexes = revokedUserIndexes;
85 | }
86 |
87 | public void writeToStream(AbeOutputStream stream) throws IOException {
88 | stream.writeInt(SERIALIZE_VERSION);
89 |
90 | boolean isAccessStructure = isAccessMatrix();
91 | stream.writeBoolean(isAccessStructure);
92 | if (isAccessStructure) {
93 | accessMatrix.writeToStream(stream);
94 | } else {
95 | accessTree.writeToStream(stream);
96 | }
97 | Lw14Util.writeArray(r1, stream);
98 | Lw14Util.writeArray(r2, stream);
99 | Lw14Util.writeArray(q1, stream);
100 | Lw14Util.writeArray(q2, stream);
101 | Lw14Util.writeArray(q3, stream);
102 | Lw14Util.writeArray(t, stream);
103 | Lw14Util.writeArray(c1, stream);
104 | Lw14Util.writeArray(c2, stream);
105 | if (isAccessStructure) {
106 | Lw14Util.writeArray(p1, stream);
107 | Lw14Util.writeArray(p2, stream);
108 | Lw14Util.writeArray(p3, stream);
109 | }
110 | stream.writeBoolean(policy != null);
111 | if (policy != null) {
112 | stream.writeString(policy);
113 | }
114 | Lw14Util.writeArray(revokedUserIndexes, stream);
115 | }
116 |
117 | public boolean isAccessMatrix() {
118 | return accessMatrix != null;
119 | }
120 |
121 | @Override
122 | public boolean equals(Object ct) {
123 | if (ct == null || !(ct instanceof CipherText)) {
124 | return false;
125 | } else if(this == ct) {
126 | return true;
127 | }
128 | CipherText c = (CipherText)ct;
129 |
130 | boolean result = isAccessMatrix() == c.isAccessMatrix();
131 | if (isAccessMatrix()) {
132 | result = result && accessMatrix.equals(c.accessMatrix);
133 | } else {
134 | result = result && accessTree.equals(c.accessTree);
135 | }
136 | result = result && Arrays.equals(r1, c.r1);
137 | result = result && Arrays.equals(r2, c.r2);
138 | result = result && Arrays.equals(q1, c.q1);
139 | result = result && Arrays.equals(q2, c.q2);
140 | result = result && Arrays.equals(q3, c.q3);
141 | result = result && Arrays.equals(t, c.t);
142 | result = result && Arrays.equals(c1, c.c1);
143 | result = result && Arrays.equals(c2, c.c2);
144 | result = result && Arrays.equals(p1, c.p1);
145 | result = result && Arrays.equals(p2, c.p2);
146 | result = result && Arrays.equals(p3, c.p3);
147 | result = result && ((policy == null && c.policy == null) || (policy != null && policy.equals(c.policy)));
148 | result = result && Arrays.equals(revokedUserIndexes, c.revokedUserIndexes);
149 |
150 | return result;
151 | }
152 |
153 | public static CipherText readFromStream(AbeInputStream stream) throws IOException {
154 | int version = stream.readInt();
155 |
156 | CipherText ct = new CipherText();
157 |
158 | boolean isAccessStructure = stream.readBoolean();
159 | if (isAccessStructure) {
160 | ct.accessMatrix = LsssMatrix.readFromStream(stream);
161 | } else {
162 | ct.accessTree = Lw14PolicyAbstractNode.readFromStream(stream);
163 | }
164 |
165 | ct.r1 = Lw14Util.readElementVectorArray(stream);
166 | ct.r2 = Lw14Util.readElementVectorArray(stream);
167 | ct.q1 = Lw14Util.readElementArray(stream);
168 | ct.q2 = Lw14Util.readElementArray(stream);
169 | ct.q3 = Lw14Util.readElementArray(stream);
170 | ct.t = Lw14Util.readElementArray(stream);
171 | ct.c1 = Lw14Util.readElementVectorArray(stream);
172 | ct.c2 = Lw14Util.readElementVectorArray(stream);
173 | if (isAccessStructure) {
174 | ct.p1 = Lw14Util.readElementArray(stream);
175 | ct.p2 = Lw14Util.readElementArray(stream);
176 | ct.p3 = Lw14Util.readElementArray(stream);
177 | }
178 | if (stream.readBoolean()) {
179 | ct.policy = stream.readString();
180 | }
181 | ct.revokedUserIndexes = Lw14Util.readIntegerArray(stream);
182 |
183 | return ct;
184 | }
185 |
186 | public byte[] getAsByteArray(AbePublicKey pub) throws IOException {
187 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
188 | AbeOutputStream stream = new AbeOutputStream(baos, pub);
189 | this.writeToStream(stream);
190 | return baos.toByteArray();
191 | }
192 |
193 | public static CipherText readFromByteArray(byte[] data, AbePublicKey pub) throws IOException {
194 | AbeInputStream stream = new AbeInputStream(new ByteArrayInputStream(data), pub);
195 | try {
196 | return readFromStream(stream);
197 | } finally {
198 | stream.close();
199 | }
200 | }
201 |
202 | public static int getSerializeVersion() {
203 | return SERIALIZE_VERSION;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/Lw14DecryptionBlackBox.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | /**
6 | * The decryption black box may consist of multiple keys from different users
7 | * which makes up a whole. It may act probabilistically and decrypt ciphertexts
8 | * which use some but not all attributes of the users that the black box was
9 | * built from.
10 | */
11 | public abstract class Lw14DecryptionBlackBox {
12 |
13 | /**
14 | * Determine if the given cipher text can be decrypted using this black box.
15 | * @param ct Cipher text
16 | * @return is decryptable
17 | */
18 | public boolean canDecrypt(CipherText ct) {
19 | Element pt = decrypt(ct);
20 | return pt != null;
21 | }
22 |
23 | /**
24 | * Determine if the given cipher text can be decrypted using this black box.
25 | * @param ct Cipher text
26 | * @return is decryptable
27 | */
28 | public abstract Element decrypt(CipherText ct);
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/Lw14MockBlackBox.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 | import trabe.AbeDecryptionException;
5 | import trabe.AbePrivateKey;
6 | import trabe.AbePublicKey;
7 | import trabe.policyparser.ParseException;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | public class Lw14MockBlackBox extends Lw14DecryptionBlackBox {
14 |
15 | public List userKeys = new ArrayList();
16 | public AbePublicKey publicKey;
17 |
18 | public Lw14MockBlackBox(List userKeys, AbePublicKey publicKey) {
19 | this.userKeys = userKeys;
20 | this.publicKey = publicKey;
21 | }
22 |
23 | public Lw14MockBlackBox(AbePrivateKey[] userKeys, AbePublicKey publicKey) {
24 | this.userKeys = new ArrayList(userKeys.length);
25 | Collections.addAll(this.userKeys, userKeys);
26 | this.publicKey = publicKey;
27 | }
28 |
29 | /**
30 | * Determine if the given cipher text can be decrypted using this black box.
31 | *
32 | * @param ct Cipher text
33 | * @return is decryptable
34 | */
35 | @Override
36 | public Element decrypt(CipherText ct) {
37 | for(AbePrivateKey key : userKeys) {
38 | try {
39 | if (Lw14.canDecrypt(key, ct)) {
40 | return Lw14.decrypt(key, ct);
41 | }
42 | } catch (ParseException e) {
43 | System.err.println("Decrypting with key with index " + userKeys.indexOf(key) + " failed");
44 | e.printStackTrace();
45 | } catch (AbeDecryptionException e) {
46 |
47 | }
48 | }
49 | return null;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/Lw14Polynomial.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | public class Lw14Polynomial {
6 | /* coefficients from [0] x^0 to [deg] x^deg */
7 | public Element[] coef; /* G_T (of length deg+1) */
8 |
9 | private Lw14Polynomial(int deg) {
10 | coef = new Element[deg + 1];
11 | }
12 |
13 | /**
14 | * Generates a new polynomial with random coefficients of the element type given as zeroVal. The 0th coefficient has the same
15 | * value as zeroVal.
16 | *
17 | * @param deg number of coefficients
18 | * @param zeroVal Zero element
19 | * @return Random polynomial
20 | */
21 | public static Lw14Polynomial createRandom(int deg, Element zeroVal) {
22 | Lw14Polynomial newPoly = new Lw14Polynomial(deg);
23 | for (int i = 0; i < newPoly.coef.length; i++)
24 | newPoly.coef[i] = zeroVal.duplicate();
25 |
26 | newPoly.coef[0].set(zeroVal);
27 |
28 | for (int i = 1; i < newPoly.coef.length; i++)
29 | newPoly.coef[i].setToRandom();
30 | return newPoly;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/Lw14PrivateKeyComponent.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 | import trabe.AbeInputStream;
5 | import trabe.AbeOutputStream;
6 |
7 | import java.io.IOException;
8 |
9 | public class Lw14PrivateKeyComponent {
10 | /* these actually get serialized */
11 |
12 | /** Z_r **/
13 | public Element hashedAttributeZr;
14 | public String attribute;
15 | /** G_1 **/
16 | public Element k1_ijx;
17 | /** G_1 **/
18 | public Element k2_ijx;
19 |
20 | public Element k1Tilde_ijx;
21 | public Element k2Tilde_ijx;
22 |
23 | private Lw14PrivateKeyComponent(){}
24 |
25 | public Lw14PrivateKeyComponent(String attribute, Element hashedAttributeZr, Element k1_ijx, Element k2_ijx, Element k1Tilde_ijx, Element k2Tilde_ijx) {
26 | this.attribute = attribute;
27 | this.hashedAttributeZr = hashedAttributeZr;
28 | this.k1_ijx = k1_ijx;
29 | this.k2_ijx = k2_ijx;
30 | this.k1Tilde_ijx = k1Tilde_ijx;
31 | this.k2Tilde_ijx = k2Tilde_ijx;
32 | }
33 |
34 | public void writeToStream(AbeOutputStream stream) throws IOException {
35 | stream.writeString(attribute);
36 | stream.writeElement(hashedAttributeZr);
37 | stream.writeElement(k1_ijx);
38 | stream.writeElement(k2_ijx);
39 | }
40 |
41 | public static Lw14PrivateKeyComponent readFromStream(AbeInputStream stream, int serializeVersion) throws IOException {
42 | Lw14PrivateKeyComponent component = new Lw14PrivateKeyComponent();
43 |
44 | component.attribute = stream.readString();
45 | if (serializeVersion < 3) {
46 | stream.readElement();
47 | }
48 | component.hashedAttributeZr = stream.readElement();
49 | component.k1_ijx = stream.readElement();
50 | component.k2_ijx = stream.readElement();
51 |
52 | return component;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object obj) {
57 | if (obj == null || !(obj instanceof Lw14PrivateKeyComponent)) {
58 | return false;
59 | } else if(this == obj) {
60 | return true;
61 | }
62 | Lw14PrivateKeyComponent component = (Lw14PrivateKeyComponent)obj;
63 |
64 | boolean result = attribute.equals(component.attribute);
65 | result = result && k1_ijx.equals(component.k1_ijx);
66 | result = result && k2_ijx.equals(component.k2_ijx);
67 |
68 | return result;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/Lw14Util.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | import java.io.DataInputStream;
6 | import java.io.DataOutputStream;
7 | import java.io.IOException;
8 | import java.math.BigInteger;
9 | import java.security.MessageDigest;
10 | import java.security.NoSuchAlgorithmException;
11 | import java.util.*;
12 |
13 | import trabe.*;
14 | import it.unisa.dia.gas.jpbc.Field;
15 | import trabe.lw14.policy.Lw14PolicyAbstractNode;
16 | import trabe.policy.PolicyParsing;
17 | import trabe.policyparser.*;
18 |
19 | public class Lw14Util {
20 | private enum ElementType { G1, G2, GT, Zr}
21 |
22 | private static Element elementFromString(ElementType et, String s, AbePublicKey publicKey) {
23 | try {
24 | MessageDigest hasher = MessageDigest.getInstance(AbeSettings.ELEMENT_HASHING_ALGORITHM);
25 | byte[] digest = hasher.digest(s.getBytes());
26 | Field field;
27 | switch (et){
28 | case G1:
29 | field = publicKey.getPairing().getG1();
30 | break;
31 | case G2:
32 | field = publicKey.getPairing().getG2();
33 | break;
34 | case GT:
35 | field = publicKey.getPairing().getGT();
36 | break;
37 | case Zr:
38 | field = publicKey.getPairing().getZr();
39 | break;
40 | default:
41 | return null;
42 | }
43 | return field.newElementFromHash(digest, 0, digest.length);
44 | } catch (NoSuchAlgorithmException e) {
45 | e.printStackTrace();
46 | System.exit(1);
47 | }
48 | return null;
49 | }
50 |
51 | public static Element elementG1FromString(String s, AbePublicKey publicKey) {
52 | return elementFromString(ElementType.G1, s, publicKey);
53 | }
54 |
55 | public static Element elementG2FromString(String s, AbePublicKey publicKey) {
56 | return elementFromString(ElementType.G2, s, publicKey);
57 | }
58 |
59 | public static Element elementGtFromString(String s, AbePublicKey publicKey) {
60 | return elementFromString(ElementType.GT, s, publicKey);
61 | }
62 |
63 | public static Element elementZrFromString(String s, AbePublicKey publicKey) {
64 | return elementFromString(ElementType.Zr, s, publicKey);
65 | }
66 |
67 | public static void writeArray(Element[] array, AbeOutputStream stream) throws IOException {
68 | writeArray(array, stream, true);
69 | }
70 |
71 | public static void writeArray(Element[] array, AbeOutputStream stream, boolean withHeader) throws IOException {
72 | if (withHeader){
73 | stream.writeInt(array.length);
74 | }
75 | for(int i = 0; i < array.length; i++) {
76 | stream.writeElement(array[i]);
77 | }
78 | }
79 |
80 | public static void writeArray(int[] array, AbeOutputStream stream) throws IOException {
81 | writeArray(array, stream, true);
82 | }
83 |
84 | public static void writeArray(int[] array, AbeOutputStream stream, boolean withHeader) throws IOException {
85 | if (withHeader){
86 | stream.writeInt(array.length);
87 | }
88 | for(int i = 0; i < array.length; i++) {
89 | stream.writeInt(array[i]);
90 | }
91 | }
92 |
93 | public static void writeArray(ElementVector[] array, AbeOutputStream stream) throws IOException {
94 | writeArray(array, stream, true);
95 | }
96 |
97 | public static void writeArray(ElementVector[] array, AbeOutputStream stream, boolean withHeader) throws IOException {
98 | if (withHeader) {
99 | stream.writeInt(array.length);
100 | }
101 | for (ElementVector vec : array) {
102 | vec.writeToStream(stream);
103 | }
104 | }
105 |
106 | public static void writeArray(byte[] array, DataOutputStream stream) throws IOException {
107 | if (array == null || array.length == 0) {
108 | stream.writeInt(0);
109 | } else {
110 | stream.writeInt(array.length);
111 | stream.write(array);
112 | }
113 | }
114 |
115 | public static Element[] readElementArray(AbeInputStream stream) throws IOException {
116 | int len = stream.readInt();
117 | return readElementArray(len, stream);
118 | }
119 |
120 | public static Element[] readElementArray(int length, AbeInputStream stream) throws IOException {
121 | Element[] vec = new Element[length];
122 | for(int i = 0; i < length; i++) {
123 | vec[i] = stream.readElement();
124 | }
125 | return vec;
126 | }
127 |
128 | public static int[] readIntegerArray(AbeInputStream stream) throws IOException {
129 | int len = stream.readInt();
130 | return readIntegerArray(len, stream);
131 | }
132 |
133 | public static int[] readIntegerArray(int length, AbeInputStream stream) throws IOException {
134 | int[] vec = new int[length];
135 | for(int i = 0; i < length; i++) {
136 | vec[i] = stream.readInt();
137 | }
138 | return vec;
139 | }
140 |
141 | public static byte[] readByteArray(DataInputStream stream) throws IOException {
142 | int len = stream.readInt();
143 | byte[] result = new byte[len];
144 | stream.read(result);
145 | return result;
146 | }
147 |
148 | public static ElementVector[] readElementVectorArray(AbeInputStream stream) throws IOException {
149 | int len = stream.readInt();
150 | return readElementVectorArray(len, stream);
151 | }
152 |
153 | public static ElementVector[] readElementVectorArray(int length, AbeInputStream stream) throws IOException {
154 | ElementVector[] vec = new ElementVector[length];
155 | for(int i = 0; i < length; i++) {
156 | vec[i] = ElementVector.readFromStream(stream);
157 | }
158 | return vec;
159 | }
160 |
161 | public static String getSpaces(int number) {
162 | StringBuilder sb = new StringBuilder(number);
163 | for(int i = 0; i < number; i++) {
164 | sb.append(" ");
165 | }
166 | return sb.toString();
167 | }
168 |
169 | private static AbePrivateKey mockPrivateKey(Set attributes, AbePublicKey publicKey) {
170 | ArrayList components = new ArrayList();
171 | for (String s : attributes) {
172 | components.add(new Lw14PrivateKeyComponent(s, elementZrFromString(s, publicKey), null, null,null, null));
173 | }
174 | return new AbePrivateKey(null, null, null, null, null, components, publicKey);
175 | }
176 |
177 | public static Lw14PolicyAbstractNode getPolicyTree(String policy, AbePublicKey publicKey) throws ParseException {
178 | String postFixPolicy = PolicyParsing.parsePolicy(policy);
179 | return Lw14PolicyAbstractNode.parsePolicy(postFixPolicy, publicKey);
180 | }
181 |
182 | public static boolean satisfies(String policy, AbePrivateKey privateKey) throws ParseException {
183 | return satisfies(getPolicyTree(policy, privateKey.getPublicKey()), privateKey);
184 | }
185 |
186 | public static boolean satisfies(Lw14PolicyAbstractNode policy, AbePrivateKey privateKey) {
187 | return policy.checkSatisfy(privateKey);
188 | }
189 |
190 | /**
191 | * Generates a parse tree and uses it to check whether the passed set of attributes satisfies the access tree.
192 | *
193 | * @param policy policy
194 | * @param set Attribute string set
195 | * @return Set satisfies the policy
196 | * @throws ParseException Policy parsing failed
197 | */
198 | public static boolean satisfies(String policy, Set set, AbePublicKey publicKey) throws ParseException {
199 | return satisfies(policy, mockPrivateKey(set, publicKey));
200 | }
201 |
202 | /**
203 | * Uses the parse tree to check whether the passed set of attributes satisfies the access tree.
204 | *
205 | * @param policyTree Root node of the tree
206 | * @param set Attribute string set
207 | * @param publicKey Public key for some internal elements
208 | * @return Set satisfies the tree
209 | */
210 | public static boolean satisfies(Lw14PolicyAbstractNode policyTree, Set set, AbePublicKey publicKey) {
211 | return satisfies(policyTree, mockPrivateKey(set, publicKey));
212 | }
213 |
214 | /**
215 | * Computes the power set of the original set, but limits the items to a length or length
.
216 | * @param originalSet Original items as a set
217 | * @param length Intended length of the items of the power set
218 | * @param Item type
219 | * @return filtered power set
220 | */
221 | public static Set> powerSet(Set originalSet, int length) {
222 | if (originalSet.size() < length) {
223 | throw new RuntimeException("Filter length cannot be larger than the set size");
224 | }
225 | Set> sets = powerSet(originalSet);
226 | Set> removeSet = new HashSet>();
227 | for (Set set : sets) {
228 | if (set.size() != length) {
229 | removeSet.add(set);
230 | }
231 | }
232 | sets.removeAll(removeSet);
233 | return sets;
234 | }
235 |
236 | /**
237 | * Computes the power set of the given set.
238 | * Copied from StackOverflow by João Silva.
239 | * @param originalSet Set to build the power set from
240 | * @param Set element type
241 | * @return Power set of {@code T}
242 | */
243 | public static Set> powerSet(Set originalSet) {
244 | Set> sets = new HashSet>();
245 | if (originalSet.isEmpty()) {
246 | sets.add(new HashSet());
247 | return sets;
248 | }
249 | List list = new ArrayList(originalSet);
250 | T head = list.get(0);
251 | Set rest = new HashSet(list.subList(1, list.size()));
252 | for (Set set : powerSet(rest)) {
253 | Set newSet = new HashSet();
254 | newSet.add(head);
255 | newSet.addAll(set);
256 | sets.add(newSet);
257 | sets.add(set);
258 | }
259 | return sets;
260 | }
261 |
262 | public static String toString(Element[] array, int initialIndent, int additionalIndent){
263 | return toString(Arrays.asList(array), initialIndent, additionalIndent);
264 | }
265 |
266 | public static String toString(Collection collection, int initialIndent, int additionalIndent){
267 | StringBuilder sb;
268 |
269 | String iiString = getSpaces(initialIndent);
270 | String aiString = getSpaces(additionalIndent);
271 |
272 | sb = new StringBuilder();
273 | sb.append(iiString);
274 | sb.append("[\n");
275 | int i = 0;
276 | for(Element el : collection) {
277 | if (i != 0) {
278 | sb.append(",\n");
279 | }
280 | sb.append(iiString);
281 | sb.append(aiString);
282 | sb.append('"');
283 | sb.append(el);
284 | sb.append('"');
285 | i++;
286 | }
287 | sb.append("\n");
288 | sb.append(iiString);
289 | sb.append("]");
290 | return sb.toString();
291 | }
292 |
293 | /**
294 | * Returns one pascal row as array. For example would be
295 | * getPascalRow(4) == { 1, 3, 3, 1}
296 | * @param n Pascal row index
297 | * @return Row as long array
298 | */
299 | public static long[] getPascalRow(int n) {
300 | long[] row = new long[n];
301 | row[0] = 1L;
302 |
303 | for(int col = 1; col < n; col++) {
304 | row[col] = row[col - 1] * (n - col) / col;
305 | }
306 |
307 | return row;
308 | }
309 |
310 | /**
311 | * It computes lexicographically the next permutation of the bits in the given number.
312 | *
313 | * For example 3 = 0b000011
314 | * - next: 0b000101 (5)
315 | * - next: 0b000110 (6)
316 | * - next: 0b001001 (9)
317 | * - next: 0b001010 (10)
318 | * - next: 0b001100 (12)
319 | * - next: 0b010001 (17)
320 | *
321 | * Copied from Bit Twiddling Hacks: Compute the lexicographically next bit permutation
322 | * @param v Source number
323 | * @return Bit-twiddled number
324 | */
325 | public static long getNextLexicographicalPermutation(long v) {
326 | long t = (v | (v - 1)) + 1;
327 | return t | ((((t & -t) / (v & -v)) >> 1) - 1);
328 | }
329 |
330 | /**
331 | * It computes lexicographically the next permutation of the bits in the given number.
332 | *
333 | * For example 3 = 0b000011
334 | * - next: 0b000101 (5)
335 | * - next: 0b000110 (6)
336 | * - next: 0b001001 (9)
337 | * - next: 0b001010 (10)
338 | * - next: 0b001100 (12)
339 | * - next: 0b010001 (17)
340 | *
341 | * Copied from Bit Twiddling Hacks: Compute the lexicographically next bit permutation
342 | * @param v Source number
343 | * @return Bit-twiddled number
344 | */
345 | public static BigInteger getNextLexicographicalPermutation(BigInteger v) {
346 | BigInteger t = v.or(v.subtract(BigInteger.ONE)).add(BigInteger.ONE);
347 | return t.and(t.negate()).divide(v.and(v.negate())).shiftRight(1).subtract(BigInteger.ONE).or(t);
348 | }
349 | }
350 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/SortedPowerSet.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import java.util.Iterator;
4 | import java.util.Set;
5 |
6 | public class SortedPowerSet implements Iterable> {
7 | private Iterator> iterator;
8 |
9 | public SortedPowerSet(Set set){
10 | iterator = new SortedPowerSetIterator(set);
11 | }
12 |
13 | @Override
14 | public Iterator> iterator() {
15 | return iterator;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/SortedPowerSetIterator.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14;
2 |
3 | import java.math.BigInteger;
4 | import java.util.*;
5 |
6 | /**
7 | * This iterator uses the provided set to generate a power set of it on the fly.
8 | * The size of the elements of the power set is monotonously increasing. For
9 | * example the firs element of the iteration is always an empty set and the last
10 | * iteration is the full set that was provided.
11 | *
12 | * It has a constant amount of internal objects during its execution.
13 | * @param Element type
14 | */
15 | public class SortedPowerSetIterator implements Iterator> {
16 | private T[] elements;
17 |
18 | private long[] buckets;
19 | private int currentBucketIndex;
20 | private int currentIndexInBucket;
21 | private BigInteger currentPermutation;
22 |
23 | @SuppressWarnings("unchecked")
24 | public SortedPowerSetIterator(Set set) {
25 | elements = (T[])set.toArray();
26 | buckets = Lw14Util.getPascalRow(set.size()+1);
27 | currentBucketIndex = 0;
28 | currentIndexInBucket = 0;
29 | }
30 |
31 | @Override
32 | public boolean hasNext() {
33 | return (currentIndexInBucket+1 < buckets[currentBucketIndex]) ||
34 | (currentBucketIndex+1 < buckets.length);
35 | }
36 |
37 | @Override
38 | public Set next() {
39 | if (currentPermutation == null) {
40 | currentPermutation = BigInteger.ZERO;
41 | return new HashSet();
42 | }
43 | if (currentIndexInBucket+1 < buckets[currentBucketIndex]) {
44 | currentIndexInBucket++;
45 | currentPermutation = Lw14Util.getNextLexicographicalPermutation(currentPermutation);
46 | } else if (currentBucketIndex+1 < buckets.length) {
47 | currentIndexInBucket = 0;
48 | currentBucketIndex++;
49 |
50 | // compute 2^bucketIndex - 1 to get the starting permutation
51 | BigInteger two = BigInteger.valueOf(2);
52 | currentPermutation = two.pow(currentBucketIndex).add(BigInteger.ONE.negate());
53 | } else {
54 | throw new NoSuchElementException();
55 | }
56 | return getSetFromBits(currentPermutation);
57 | }
58 |
59 | @Override
60 | public void remove() {
61 | throw new RuntimeException("Not implemented");
62 | }
63 |
64 | /**
65 | * Create a set that is an element of the power set represented by the passed permutation/bits.
66 | * @param bits Permutation of the initial set signified by bits
67 | * @return Subset of the underlying set derived from the given {@code bits}
68 | */
69 | private Set getSetFromBits(BigInteger bits) {
70 | Set set = new HashSet();
71 |
72 | int bitCount = bits.bitCount();
73 | int counted = 0;
74 | int i = 0;
75 | while(counted < bitCount) {
76 | if (bits.testBit(i)) {
77 | set.add(elements[i]);
78 | counted++;
79 | }
80 | i++;
81 | }
82 | return set;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/policy/LsssMatrixCell.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14.policy;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 | import trabe.AbeInputStream;
5 | import trabe.AbeOutputStream;
6 |
7 | import java.io.IOException;
8 |
9 | /**
10 | *
11 | */
12 | public class LsssMatrixCell {
13 | public int i;
14 | public int j;
15 | public int value;
16 | public String attribute;
17 | public Element hashedElement;
18 |
19 | private LsssMatrixCell(){}
20 |
21 | public LsssMatrixCell(int i, int j, int value, String attribute, Element hashedElement) {
22 | this.i = i;
23 | this.j = j;
24 | this.value = value;
25 | this.attribute = attribute;
26 | this.hashedElement = hashedElement;
27 | }
28 |
29 | public String toString(){
30 | return "["+i+","+j+"] " + attribute + ": " + value + "(" + hashedElement + ")";
31 | }
32 |
33 | public void writeToStream(AbeOutputStream stream) throws IOException {
34 | stream.writeInt(value);
35 | stream.writeString(attribute);
36 | stream.writeElement(hashedElement);
37 | }
38 |
39 | public static LsssMatrixCell readFromStream(AbeInputStream stream) throws IOException {
40 | LsssMatrixCell cell = new LsssMatrixCell();
41 |
42 | cell.value = stream.readInt();
43 | cell.attribute = stream.readString();
44 | cell.hashedElement = stream.readElement();
45 |
46 | return cell;
47 | }
48 |
49 | @Override
50 | public boolean equals(Object obj) {
51 | if (obj == null || !(obj instanceof LsssMatrixCell)) {
52 | return false;
53 | } else if(this == obj) {
54 | return true;
55 | }
56 | LsssMatrixCell c = (LsssMatrixCell)obj;
57 | return i == c.i && j == c.j && value == c.value && attribute.equals(c.attribute) && hashedElement.equals(c.hashedElement);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/policy/Lw14PolicyAbstractNode.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14.policy;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 | import java.util.regex.Pattern;
7 |
8 | import it.unisa.dia.gas.jpbc.ElementPowPreProcessing;
9 | import trabe.AbeInputStream;
10 | import trabe.AbeOutputStream;
11 | import trabe.AbePrivateKey;
12 | import trabe.AbePublicKey;
13 | import it.unisa.dia.gas.jpbc.Element;
14 | import trabe.policyparser.ParseException;
15 |
16 | public abstract class Lw14PolicyAbstractNode {
17 | protected boolean satisfiable;
18 | protected int minLeaves;
19 |
20 | public int getMinLeaves() {
21 | return minLeaves;
22 | }
23 |
24 | public abstract void fillPolicy(AbePublicKey pub, Element e);
25 |
26 | public abstract void fillPolicy(AbePublicKey pub, Element e, Lw14TreePreprocessing tpp);
27 |
28 | protected abstract boolean checkSatisfySpecific(AbePrivateKey prv);
29 |
30 | public boolean checkSatisfy(AbePrivateKey prv) {
31 | satisfiable = checkSatisfySpecific(prv);
32 | return satisfiable;
33 | }
34 |
35 | public abstract void pickSatisfyMinLeaves(AbePrivateKey prv);
36 |
37 | protected abstract void decFlattenSpecific(Element r, Element one, AbePrivateKey prv);
38 |
39 | public void decFlatten(Element r, AbePrivateKey prv) {
40 | Element one = prv.getPublicKey().getPairing().getZr().newOneElement();
41 | r.setToOne();
42 | decFlattenSpecific(r, one, prv);
43 | }
44 |
45 | public abstract int getThreshold();
46 |
47 | public abstract void writeToStream(AbeOutputStream stream) throws IOException;
48 |
49 | public static Lw14PolicyAbstractNode readFromStream(AbeInputStream stream) throws IOException {
50 | int threshold = stream.readInt();
51 | int numberOfChildren = stream.readInt();
52 | if (numberOfChildren == 0) { // is leaf
53 | Element hashedAttribute = stream.readElement();
54 | Element p1 = stream.readElement();
55 | Element p2 = stream.readElement();
56 | Element p3 = stream.readElement();
57 | return new Lw14PolicyLeafNode(hashedAttribute, p1, p2, p3);
58 | } else {
59 | Lw14PolicyParentNode tmp = new Lw14PolicyParentNode(threshold, numberOfChildren);
60 | for (int i = 0; i < numberOfChildren; i++) {
61 | Lw14PolicyAbstractNode readPolicy = Lw14PolicyAbstractNode.readFromStream(stream);
62 | tmp.addChild(readPolicy);
63 | }
64 | return tmp;
65 | }
66 | }
67 |
68 | private static final String of = "^([0-9]+)of([0-9]+)$";
69 | private static final Pattern ofPattern = Pattern.compile(of);
70 |
71 | public static Lw14PolicyAbstractNode parsePolicy(String s, AbePublicKey publicKey) throws ParseException {
72 | ArrayList stack = new ArrayList();
73 | String[] toks = s.split("\\s+");
74 | for (int index = 0; index < toks.length; index++) {
75 | String curToken = toks[index];
76 | if (!ofPattern.matcher(curToken).matches()) {
77 | stack.add(new Lw14PolicyLeafNode(curToken, publicKey));
78 | } else {
79 | String[] k_n = curToken.split("of"); /* parse kofn node */
80 | int threshold = Integer.parseInt(k_n[0]);
81 | int numChildren = Integer.parseInt(k_n[1]);
82 |
83 | if (threshold < 1) {
84 | throw new ParseException("error parsing " + s + ": trivially satisfied operator " + curToken);
85 | } else if (threshold > numChildren) {
86 | throw new ParseException("error parsing " + s + ": unsatisfiable operator " + curToken);
87 | } else if (numChildren == 1) {
88 | throw new ParseException("error parsing " + s + ": indentity operator " + curToken);
89 | } else if (numChildren > stack.size()) {
90 | throw new ParseException("error parsing " + s + ": stack underflow at " + curToken);
91 | }
92 |
93 | /* pop n things and fill in children */
94 | Lw14PolicyParentNode node = new Lw14PolicyParentNode(threshold, numChildren);
95 | Lw14PolicyAbstractNode[] tmp = new Lw14PolicyAbstractNode[numChildren];
96 |
97 | for (int i = numChildren - 1; i >= 0; i--)
98 | tmp[i] = stack.remove(stack.size() - 1);
99 |
100 | node.addAllChildren(Arrays.asList(tmp));
101 | /* push result */
102 | stack.add(node);
103 | }
104 | }
105 |
106 | if (stack.size() > 1) {
107 | throw new ParseException("error parsing " + s + ": extra node left on the stack");
108 | } else if (stack.size() < 1) {
109 | throw new ParseException("error parsing " + s + ": empty policy");
110 | }
111 | return stack.get(0); // the root of the tree
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/policy/Lw14PolicyLeafNode.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14.policy;
2 |
3 | import java.io.IOException;
4 |
5 | import it.unisa.dia.gas.jpbc.ElementPowPreProcessing;
6 | import it.unisa.dia.gas.jpbc.Pairing;
7 | import trabe.AbeOutputStream;
8 | import trabe.AbePrivateKey;
9 | import trabe.AbePublicKey;
10 | import trabe.AbeSettings;
11 | import trabe.lw14.Lw14PrivateKeyComponent;
12 | import trabe.lw14.Lw14Util;
13 | import it.unisa.dia.gas.jpbc.Element;
14 |
15 | public class Lw14PolicyLeafNode extends Lw14PolicyAbstractNode {
16 | private Lw14PrivateKeyComponent satisfyingComponent = null;
17 | /** G1 **/
18 | private Element hashedAttribute;
19 | /** G1 **/
20 | private Element p1;
21 | /** G1 **/
22 | private Element p2;
23 | /** G1 **/
24 | private Element p3;
25 |
26 | protected Lw14PolicyLeafNode(Element hashedAttribute, Element p1, Element p2, Element p3) {
27 | this(hashedAttribute);
28 | this.p1 = p1;
29 | this.p2 = p2;
30 | this.p3 = p3;
31 | }
32 |
33 | public Lw14PolicyLeafNode(Element hashedAttribute) {
34 | this.hashedAttribute = hashedAttribute;
35 | }
36 |
37 | public Lw14PolicyLeafNode(String attribute, AbePublicKey publicKey) {
38 | hashedAttribute = Lw14Util.elementZrFromString(attribute, publicKey);
39 | }
40 |
41 | public int getThreshold() {
42 | return 1;
43 | }
44 |
45 | private Element getHashedAttribute() {
46 | return hashedAttribute;
47 | }
48 |
49 | @Override
50 | public void writeToStream(AbeOutputStream stream) throws IOException {
51 | stream.writeInt(getThreshold());
52 | stream.writeInt(0);
53 | stream.writeElement(hashedAttribute);
54 | stream.writeElement(p1);
55 | stream.writeElement(p2);
56 | stream.writeElement(p3);
57 | }
58 |
59 | @Override
60 | public void fillPolicy(AbePublicKey pub, Element e) {
61 | Element b = pub.getPairing().getZr().newRandomElement();
62 |
63 | p1 = pub.f.duplicate().powZn(e)
64 | .mul(pub.G.duplicate().powZn(b));
65 | p2 = pub.H.duplicate().powZn(hashedAttribute)
66 | .mul(pub.h).powZn(b.duplicate().negate());
67 | p3 = pub.g.duplicate().powZn(b);
68 | }
69 |
70 | @Override
71 | public void fillPolicy(AbePublicKey pub, Element e, Lw14TreePreprocessing tpp) {
72 | Element b = pub.getPairing().getZr().newRandomElement();
73 |
74 | p1 = tpp.eppp_f.powZn(e)
75 | .mul(tpp.eppp_G.powZn(b));
76 | p2 = tpp.eppp_H.powZn(hashedAttribute)
77 | .mul(pub.h).powZn(b.duplicate().negate());
78 | p3 = tpp.eppp_g.powZn(b);
79 | }
80 |
81 | @Override
82 | protected boolean checkSatisfySpecific(AbePrivateKey prv) {
83 | satisfyingComponent = prv.getSatisfyingComponent(getHashedAttribute());
84 | return satisfyingComponent != null;
85 | }
86 |
87 | @Override
88 | public void pickSatisfyMinLeaves(AbePrivateKey prv) {
89 | minLeaves = 1;
90 | }
91 |
92 | @Override
93 | protected void decFlattenSpecific(Element r, Element exp, AbePrivateKey prv) {
94 | Pairing p = prv.getPublicKey().getPairing();
95 | Element c = null;
96 | if (AbeSettings.PREPROCESSING) {
97 | if (prv.k2_ij_pp == null) {
98 | prv.k2_ij_pp = p.getPairingPreProcessingFromElement(prv.k2_ij);
99 | }
100 | c = prv.k2_ij_pp.pairing(p1);
101 | } else {
102 | c = p.pairing(prv.k2_ij, p1);
103 | }
104 | r.mul(c.mul(p.pairing(satisfyingComponent.k1_ijx, p2))
105 | .mul(p.pairing(satisfyingComponent.k2_ijx, p3))
106 | .powZn(exp));
107 | }
108 |
109 | @Override
110 | public boolean equals(Object obj) {
111 | if (obj == null || !(obj instanceof Lw14PolicyLeafNode)) {
112 | return false;
113 | } else if(this == obj) {
114 | return true;
115 | }
116 |
117 | Lw14PolicyLeafNode leaf = (Lw14PolicyLeafNode)obj;
118 |
119 | boolean result = hashedAttribute.equals(leaf.getHashedAttribute());
120 | result = result & p1.equals(leaf.p1);
121 | result = result & p2.equals(leaf.p2);
122 | result = result & p3.equals(leaf.p3);
123 |
124 | return result;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/policy/Lw14PolicyParentNode.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14.policy;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | import java.io.IOException;
6 | import java.util.ArrayList;
7 | import java.util.Collections;
8 | import java.util.Comparator;
9 | import java.util.List;
10 |
11 | import trabe.AbeOutputStream;
12 | import trabe.AbePrivateKey;
13 | import trabe.AbePublicKey;
14 | import trabe.lw14.Lw14Polynomial;
15 |
16 | public class Lw14PolicyParentNode extends Lw14PolicyAbstractNode {
17 | private int threshold;
18 | private ArrayList children;
19 | private ArrayList satl;
20 | private Lw14Polynomial poly;
21 |
22 | public Lw14PolicyParentNode(int threshold, int numberOfChildren) {
23 | this.threshold = threshold;
24 | children = new ArrayList(numberOfChildren);
25 | }
26 |
27 | public boolean addChild(Lw14PolicyAbstractNode child) {
28 | return children.add(child);
29 | }
30 |
31 | public boolean addAllChildren(List newChildren) {
32 | return children.addAll(newChildren);
33 | }
34 |
35 | public int getThreshold() {
36 | return threshold;
37 | }
38 |
39 | public List getChildren() {
40 | return children;
41 | }
42 |
43 | @Override
44 | public void writeToStream(AbeOutputStream stream) throws IOException {
45 | stream.writeInt(getThreshold());
46 | stream.writeInt(children.size());
47 | for (Lw14PolicyAbstractNode child : children) {
48 | child.writeToStream(stream);
49 | }
50 | }
51 |
52 | @Override
53 | public void fillPolicy(AbePublicKey pub, Element e) {
54 | poly = Lw14Polynomial.createRandom(getThreshold() - 1, e);
55 | for (int i = 0; i < children.size(); i++) {
56 | Element r = pub.getPairing().getZr().newElement(i + 1);
57 | Element t = evalPoly(poly, r);
58 | children.get(i).fillPolicy(pub, t);
59 | }
60 | }
61 |
62 | @Override
63 | public void fillPolicy(AbePublicKey pub, Element e, Lw14TreePreprocessing tpp) {
64 | poly = Lw14Polynomial.createRandom(getThreshold() - 1, e);
65 | for (int i = 0; i < children.size(); i++) {
66 | Element r = pub.getPairing().getZr().newElement(i + 1);
67 | Element t = evalPoly(poly, r);
68 | children.get(i).fillPolicy(pub, t, tpp);
69 | }
70 | }
71 |
72 | private static Element evalPoly(Lw14Polynomial q, Element x) {
73 | Element r = x.duplicate().setToZero();
74 | Element t = x.duplicate().setToOne();
75 | for (Element coeff : q.coef) {
76 | r.add(coeff.duplicate().mul(t));
77 | t.mul(x);
78 | }
79 | return r;
80 | }
81 |
82 | @Override
83 | protected boolean checkSatisfySpecific(AbePrivateKey prv) {
84 | boolean canSatisfy = false;
85 | int cnt = 0;
86 | for (Lw14PolicyAbstractNode child : children)
87 | if (child.checkSatisfy(prv)) cnt++;
88 | if (cnt >= getThreshold()) canSatisfy = true;
89 | return canSatisfy;
90 | }
91 |
92 | @Override
93 | public void pickSatisfyMinLeaves(AbePrivateKey prv) {
94 | for (Lw14PolicyAbstractNode child : children)
95 | if (child.satisfiable) child.pickSatisfyMinLeaves(prv);
96 |
97 | int len = children.size();
98 | ArrayList c = new ArrayList(len);
99 | for (int i = 0; i < len; i++)
100 | c.add(new Integer(i));
101 | Collections.sort(c, new IntegerComparator(this));
102 |
103 | satl = new ArrayList();
104 | minLeaves = 0;
105 | int l = 0;
106 | for (int i = 0; i < len && l < getThreshold(); i++) {
107 | int c_i = c.get(i).intValue(); /* c[i] */
108 | Lw14PolicyAbstractNode curChild = children.get(c_i);
109 | if (curChild.satisfiable) {
110 | l++;
111 | minLeaves += curChild.minLeaves;
112 | satl.add(new Integer(c_i + 1));
113 | }
114 | }
115 | }
116 |
117 | @Override
118 | protected void decFlattenSpecific(Element r, Element exp, AbePrivateKey prv) {
119 | Element t = prv.getPublicKey().getPairing().getZr().newElement();
120 | for (Integer cur : satl) {
121 | lagrangeCoef(t, satl, cur.intValue());
122 | Element expnew = exp.duplicate().mul(t);
123 | children.get(cur - 1).decFlattenSpecific(r, expnew, prv);
124 | }
125 | }
126 |
127 | private static void lagrangeCoef(Element r, ArrayList s, int i) {
128 | Element t = r.duplicate();
129 | r.setToOne();
130 | for (Integer j : s) {
131 | if (j == i) continue;
132 | t.set(-j);
133 | r.mul(t); /* num_muls++; */
134 | t.set(i - j).invert();
135 | r.mul(t); /* num_muls++; */
136 | }
137 | }
138 |
139 | private static class IntegerComparator implements Comparator {
140 | private Lw14PolicyParentNode policy;
141 |
142 | public IntegerComparator(Lw14PolicyParentNode p) {
143 | this.policy = p;
144 | }
145 |
146 | @Override
147 | public int compare(Integer o1, Integer o2) {
148 | int k = policy.children.get(o1).minLeaves;
149 | int l = policy.children.get(o2).minLeaves;
150 | return k < l ? -1 : (k == l ? 0 : 1);
151 | }
152 | }
153 |
154 | @Override
155 | public boolean equals(Object obj) {
156 | if (obj == null || !(obj instanceof Lw14PolicyParentNode)) {
157 | return false;
158 | } else if(this == obj) {
159 | return true;
160 | }
161 |
162 | Lw14PolicyParentNode parent = (Lw14PolicyParentNode)obj;
163 |
164 | boolean result = threshold == parent.threshold;
165 | result = result & children.size() == parent.children.size();
166 | for(int i = 0; i < children.size(); i++) {
167 | result = result & children.get(i).equals(parent.children.get(i));
168 | }
169 |
170 | return result;
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/src/main/java/trabe/lw14/policy/Lw14TreePreprocessing.java:
--------------------------------------------------------------------------------
1 | package trabe.lw14.policy;
2 |
3 | import it.unisa.dia.gas.jpbc.ElementPowPreProcessing;
4 |
5 | public class Lw14TreePreprocessing {
6 | public ElementPowPreProcessing eppp_f;
7 | public ElementPowPreProcessing eppp_g;
8 | public ElementPowPreProcessing eppp_G;
9 | public ElementPowPreProcessing eppp_H;
10 |
11 | public Lw14TreePreprocessing(ElementPowPreProcessing eppp_f, ElementPowPreProcessing eppp_g, ElementPowPreProcessing eppp_G, ElementPowPreProcessing eppp_H) {
12 | this.eppp_f = eppp_f;
13 | this.eppp_g = eppp_g;
14 | this.eppp_G = eppp_G;
15 | this.eppp_H = eppp_H;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/trabe/matrixElimination/ElementField.java:
--------------------------------------------------------------------------------
1 | package trabe.matrixElimination;
2 |
3 | import it.unisa.dia.gas.jpbc.Element;
4 |
5 | public final class ElementField extends Field {
6 |
7 | public final it.unisa.dia.gas.jpbc.Field field;
8 |
9 | public ElementField(it.unisa.dia.gas.jpbc.Field field) {
10 | this.field = field;
11 | }
12 |
13 |
14 | public Element zero() {
15 | return field.newZeroElement();
16 | }
17 |
18 | public Element one() {
19 | return field.newOneElement();
20 | }
21 |
22 |
23 | public Element add(Element x, Element y) {
24 | return x.duplicate().add(y);
25 | }
26 |
27 | public Element multiply(Element x, Element y) {
28 | return x.duplicate().mul(y);
29 | }
30 |
31 |
32 | public Element negate(Element x) {
33 | return x.duplicate().negate();
34 | }
35 |
36 |
37 | public Element reciprocal(Element x) {
38 | return x.duplicate().invert();
39 | }
40 |
41 |
42 | public boolean equals(Element x, Element y) {
43 | return x.isEqual(y);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/trabe/matrixElimination/Field.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Gauss-Jordan elimination over any field (Java)
3 | *
4 | * Copyright (c) 2014 Project Nayuki
5 | * Used with permission. Contact Nayuki for licensing.
6 | * http://www.nayuki.io/page/gauss-jordan-elimination-over-any-field-java
7 | */
8 |
9 | package trabe.matrixElimination;
10 |
11 | /**
12 | * A field in abstract algebra. Every field must satisfy all these axioms, where x, y, z are arbitrary elements of the field:
13 | *
14 | * - 0 is an element of the field, and 0 + x = x. (Existence of additive identity)
15 | * - 1 is an element of the field, and 1 * x = x. (Existence of multiplicative identity)
16 | * - 0 ≠ 1. (Distinctness of additive and multiplicative identities)
17 | * - x + y = y + x. (Commutativity of addition)
18 | * - x * y = y * x. (Commutativity of multiplication)
19 | * - (x + y) + z = x + (y + z). (Associativity of addition)
20 | * - (x * y) * z = x * (y * z). (Associativity of multiplication)
21 | * - x * (y + z) = (x * y) + (x * z). (Distributivity of multiplication over addition)
22 | * - −x is an element of the field, such that x + (−x) = 0. (Existence of additive inverse)
23 | * - x−1 is an element of the field, such that x * (x−1) = 1. (Existence of multiplicative inverse)
24 | *
25 | * @param the type of the field's elements
26 | */
27 | public abstract class Field {
28 |
29 | /**
30 | * Returns the additive identity of this field.
31 | * @return the additive identity of this field
32 | */
33 | public abstract T zero();
34 |
35 | /**
36 | * Returns the multiplicative identity of this field.
37 | * @return the multiplicative identity of this field
38 | */
39 | public abstract T one();
40 |
41 |
42 | /**
43 | * Returns the sum of the two specified elements.
44 | * @param x an addend
45 | * @param y an addend
46 | * @return the sum of {@code x} and {@code y}
47 | */
48 | public abstract T add(T x, T y);
49 |
50 | /**
51 | * Returns the product of the two specified elements.
52 | * @param x a multiplicand
53 | * @param y a multiplicand
54 | * @return the product of {@code x} and {@code y}
55 | */
56 | public abstract T multiply(T x, T y);
57 |
58 | /**
59 | * Returns the additive inverse of the specified element.
60 | * @param x the element whose additive inverse to compute
61 | * @return the additive inverse of the specified element
62 | */
63 | public abstract T negate(T x);
64 |
65 | /**
66 | * Returns the multiplicative inverse of the specified element.
67 | * @param x the element whose multiplicative inverse to compute
68 | * @return the multiplicative inverse of the specified element
69 | * @throws ArithmeticException if {@code x} equals {@code zero()}
70 | */
71 | public abstract T reciprocal(T x);
72 |
73 | /**
74 | * Returns the first element minus the second element.
75 | * @param x the minuend
76 | * @param y the subtrahend
77 | * @return the first element minus the second element
78 | */
79 | public T subtract(T x, T y) {
80 | return add(x, negate(y));
81 | }
82 |
83 | /**
84 | * Returns the first element divided by the second element.
85 | * @param x the dividend
86 | * @param y the divisor
87 | * @return the first element divided by the second element
88 | * @throws ArithmeticException if {@code y} equals {@code zero()}
89 | */
90 | public T divide(T x, T y) {
91 | return multiply(x, reciprocal(y));
92 | }
93 |
94 |
95 | /**
96 | * Tests whether the two specified elements are equal.
97 | * Note that the elements are not required to implement their own {@code equals()} correctly – {@code x.equals(y)} can mismatch {@code f.equals(x, y)}.
98 | * @param x an element to test for equality
99 | * @param y an element to test for equality
100 | * @return {@code true} if the two specified elements are equal, {@code false} otherwise
101 | */
102 | public abstract boolean equals(T x, T y);
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/trabe/matrixElimination/Matrix.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Gauss-Jordan elimination over any field (Java)
3 | *
4 | * Copyright (c) 2014 Project Nayuki
5 | * Used with permission. Contact Nayuki for licensing.
6 | * http://www.nayuki.io/page/gauss-jordan-elimination-over-any-field-java
7 | */
8 |
9 | package trabe.matrixElimination;
10 |
11 | public final class Matrix implements Cloneable {
12 |
13 | /* Basic matrix implementation */
14 |
15 | // The values of the matrix stored in row-major order, with each element initially null
16 | private Object[][] values;
17 |
18 | // The field used to operate on the values in the matrix
19 | private Field f;
20 |
21 |
22 |
23 | /**
24 | * Constructs a blank matrix with the specified number of rows and columns, with operations from the specified field. All the elements are initially {@code null}.
25 | * @param rows the number of rows in this matrix
26 | * @param cols the number of columns in this matrix
27 | * @param f the field used to operate on the values in this matrix
28 | * @throws IllegalArgumentException if {@code rows} ≤ 0 or {@code cols} ≤ 0
29 | * @throws NullPointerException if {@code f} is {@code null}
30 | */
31 | public Matrix(int rows, int cols, Field f) {
32 | if (rows <= 0 || cols <= 0)
33 | throw new IllegalArgumentException("Invalid number of rows or columns");
34 | if (f == null)
35 | throw new NullPointerException();
36 |
37 | values = new Object[rows][cols];
38 | this.f = f;
39 | }
40 |
41 |
42 |
43 | /**
44 | * Returns the number of rows in this matrix, which is positive.
45 | * @return the number of rows in this matrix
46 | */
47 | public int rowCount() {
48 | return values.length;
49 | }
50 |
51 |
52 | /**
53 | * Returns the number of columns in this matrix, which is positive.
54 | * @return the number of columns in this matrix
55 | */
56 | public int columnCount() {
57 | return values[0].length;
58 | }
59 |
60 |
61 | /**
62 | * Returns the element at the specified location in this matrix.
63 | * @param row the row to read from (0-based indexing)
64 | * @param col the column to read from (0-based indexing)
65 | * @return the element at the specified location in this matrix
66 | * @throws IndexOutOfBoundsException if the specified row or column exceeds the bounds of the matrix
67 | */
68 | @SuppressWarnings("unchecked")
69 | public T get(int row, int col) {
70 | if (row < 0 || row >= values.length || col < 0 || col >= values[row].length)
71 | throw new IndexOutOfBoundsException("Row or column index out of bounds");
72 | return (T)values[row][col];
73 | }
74 |
75 |
76 | /**
77 | * Stores the specified element at the specified location in this matrix.
78 | * @param row the row to write to (0-based indexing)
79 | * @param col the column to write to (0-based indexing)
80 | * @param val the element value to write
81 | * @throws IndexOutOfBoundsException if the specified row or column exceeds the bounds of the matrix
82 | */
83 | public void set(int row, int col, T val) {
84 | if (row < 0 || row >= values.length || col < 0 || col >= values[0].length)
85 | throw new IndexOutOfBoundsException("Row or column index out of bounds");
86 | values[row][col] = val;
87 | }
88 |
89 |
90 | /**
91 | * Returns a clone of this matrix. The field and underlying values are shallow-copied because they are assumed to be immutable.
92 | * @return a clone of this matrix
93 | */
94 | public Matrix clone() {
95 | int rows = rowCount();
96 | int cols = columnCount();
97 | Matrix result = new Matrix(rows, cols, f);
98 | for (int i = 0; i < values.length; i++) // For each row
99 | System.arraycopy(values[i], 0, result.values[i], 0, cols);
100 | return result;
101 | }
102 |
103 |
104 | /* Basic matrix operations */
105 |
106 | /**
107 | * Swaps the two specified rows of this matrix.
108 | * @param row0 one row to swap (0-based indexing)
109 | * @param row1 the other row to swap (0-based indexing)
110 | * @throws IndexOutOfBoundsException if a specified row exceeds the bounds of the matrix
111 | */
112 | public void swapRows(int row0, int row1) {
113 | if (row0 < 0 || row0 >= values.length || row1 < 0 || row1 >= values.length)
114 | throw new IndexOutOfBoundsException("Row index out of bounds");
115 | Object[] temp = values[row0];
116 | values[row0] = values[row1];
117 | values[row1] = temp;
118 | }
119 |
120 |
121 | /**
122 | * Multiplies the specified row in this matrix by the specified factor. In other words, row *= factor.
123 | * @param row the row index to operate on (0-based indexing)
124 | * @param factor the factor to multiply by
125 | * @throws IndexOutOfBoundsException if the specified row exceeds the bounds of the matrix
126 | */
127 | public void multiplyRow(int row, T factor) {
128 | for (int j = 0, cols = columnCount(); j < cols; j++)
129 | set(row, j, f.multiply(get(row, j), factor));
130 | }
131 |
132 |
133 | /**
134 | * Adds the first specified row in this matrix multiplied by the specified factor to the second specified row.
135 | * In other words, destRow += srcRow * factor.
136 | * @param srcRow the index of the row to read and multiply (0-based indexing)
137 | * @param destRow the index of the row to accumulate to (0-based indexing)
138 | * @param factor the factor to multiply by
139 | * @throws IndexOutOfBoundsException if a specified row exceeds the bounds of the matrix
140 | */
141 | public void addRows(int srcRow, int destRow, T factor) {
142 | for (int j = 0, cols = columnCount(); j < cols; j++)
143 | set(destRow, j, f.add(get(destRow, j), f.multiply(get(srcRow, j), factor)));
144 | }
145 |
146 |
147 | /**
148 | * Returns the product of this matrix with the specified matrix. Requires the specified matrix to have the same number of rows as this matrix's number of columns. Remember that matrix multiplication is not commutative.
149 | * @param other the second matrix multiplicand
150 | * @return the product of this matrix with the specified matrix
151 | * @throws NullPointerException if the specified matrix is {@code null}
152 | * @throws IllegalArgumentException if the specified matrix has incompatible dimensions for multiplication
153 | */
154 | public Matrix multiply(Matrix other) {
155 | if (other == null)
156 | throw new NullPointerException();
157 | if (columnCount() != other.rowCount())
158 | throw new IllegalArgumentException("Incompatible matrix sizes for multiplication");
159 |
160 | int rows = rowCount();
161 | int cols = other.columnCount();
162 | int cells = columnCount();
163 | Matrix result = new Matrix(rows, cols, f);
164 | for (int i = 0; i < rows; i++) {
165 | for (int j = 0; j < cols; j++) {
166 | T sum = f.zero();
167 | for (int k = 0; k < cells; k++)
168 | sum = f.add(f.multiply(get(i, k), other.get(k, j)), sum);
169 | result.set(i, j, sum);
170 | }
171 | }
172 | return result;
173 | }
174 |
175 |
176 | /* Advanced matrix operation methods */
177 |
178 | /**
179 | * Converts this matrix to reduced row echelon form (RREF) using Gauss-Jordan elimination.
180 | */
181 | public void reducedRowEchelonForm() {
182 | int rows = rowCount();
183 | int cols = columnCount();
184 |
185 | // Compute row echelon form (REF)
186 | int numPivots = 0;
187 | for (int j = 0; j < cols; j++) { // For each column
188 | // Find a pivot row for this column
189 | int pivotRow = numPivots;
190 | while (pivotRow < rows && f.equals(get(pivotRow, j), f.zero()))
191 | pivotRow++;
192 | if (pivotRow == rows)
193 | continue; // Cannot eliminate on this column
194 | swapRows(numPivots, pivotRow);
195 | pivotRow = numPivots;
196 | numPivots++;
197 |
198 | // Simplify the pivot row
199 | multiplyRow(pivotRow, f.reciprocal(get(pivotRow, j)));
200 |
201 | // Eliminate rows below
202 | for (int i = pivotRow + 1; i < rows; i++)
203 | addRows(pivotRow, i, f.negate(get(i, j)));
204 | }
205 |
206 | // Compute reduced row echelon form (RREF)
207 | for (int i = rows - 1; i >= 0; i--) {
208 | // Find pivot
209 | int pivotCol = 0;
210 | while (pivotCol < cols && f.equals(get(i, pivotCol), f.zero()))
211 | pivotCol++;
212 | if (pivotCol == cols)
213 | continue; // Skip this all-zero row
214 |
215 | // Eliminate rows above
216 | for (int j = i - 1; j >= 0; j--)
217 | addRows(i, j, f.negate(get(j, pivotCol)));
218 | }
219 | }
220 |
221 |
222 | /**
223 | * Replaces the values of this matrix with the inverse of this matrix. Requires the matrix to be square. If an exception is thrown, this matrix is unchanged.
224 | * @throws IllegalStateException if this matrix is not square
225 | * @throws IllegalStateException if this matrix has no inverse
226 | */
227 | public void invert() {
228 | int rows = rowCount();
229 | int cols = columnCount();
230 | if (rows != cols)
231 | throw new IllegalStateException("Matrix dimensions are not square");
232 |
233 | // Build augmented matrix: [this | identity]
234 | Matrix temp = new Matrix(rows, cols * 2, f);
235 | for (int i = 0; i < rows; i++) {
236 | for (int j = 0; j < cols; j++) {
237 | temp.set(i, j, get(i, j));
238 | temp.set(i, j + cols, i == j ? f.one() : f.zero());
239 | }
240 | }
241 |
242 | temp.reducedRowEchelonForm();
243 |
244 | // Check that the left half is the identity matrix
245 | for (int i = 0; i < rows; i++) {
246 | for (int j = 0; j < cols; j++) {
247 | if (!f.equals(temp.get(i, j), i == j ? f.one() : f.zero()))
248 | throw new IllegalStateException("Matrix is not invertible");
249 | }
250 | }
251 |
252 | // Extract inverse matrix from: [identity | inverse]
253 | for (int i = 0; i < rows; i++) {
254 | for (int j = 0; j < cols; j++)
255 | set(i, j, temp.get(i, j + cols));
256 | }
257 | }
258 |
259 |
260 | /**
261 | * Returns the determinant of this matrix, and as a side effect converts the matrix to row echelon form (REF). Requires the matrix to be square. The leading coefficient of each row is not guaranteed to be one.
262 | * @return the determinant of this matrix
263 | * @throws IllegalStateException if this matrix is not square
264 | */
265 | public T determinantAndRef() {
266 | int rows = rowCount();
267 | int cols = columnCount();
268 | if (rows != cols)
269 | throw new IllegalStateException("Matrix dimensions are not square");
270 |
271 | T det = f.one();
272 |
273 | // Compute row echelon form (REF)
274 | int numPivots = 0;
275 | for (int j = 0; j < cols; j++) { // For each column
276 | // Find a pivot row for this column
277 | int pivotRow = numPivots;
278 | while (pivotRow < rows && f.equals(get(pivotRow, j), f.zero()))
279 | pivotRow++;
280 |
281 | if (pivotRow < rows) {
282 | // This column has a nonzero pivot
283 | if (numPivots != pivotRow) {
284 | swapRows(numPivots, pivotRow);
285 | det = f.negate(det);
286 | }
287 | pivotRow = numPivots;
288 | numPivots++;
289 |
290 | // Simplify the pivot row
291 | T temp = get(pivotRow, j);
292 | multiplyRow(pivotRow, f.reciprocal(temp));
293 | det = f.multiply(temp, det);
294 |
295 | // Eliminate rows below
296 | for (int i = pivotRow + 1; i < rows; i++)
297 | addRows(pivotRow, i, f.negate(get(i, j)));
298 | }
299 |
300 | // Update determinant
301 | det = f.multiply(get(j, j), det);
302 | }
303 |
304 | return det;
305 | }
306 |
307 | @Override
308 | public String toString(){
309 | StringBuilder sb = new StringBuilder();
310 |
311 | sb.append("[\n");
312 |
313 | for(int i = 0; i < values.length; i++) {
314 | sb.append(" [\n");
315 | for(int j = 0; j < values[i].length; j++) {
316 | sb.append(" \"").append(values[i][j]).append('"');
317 | if (j < values[i].length-1) {
318 | sb.append(",");
319 | }
320 | sb.append("\n");
321 | }
322 | sb.append(" ]");
323 | if (i < values.length-1) {
324 | sb.append(",");
325 | }
326 | sb.append("\n");
327 | }
328 |
329 | sb.append("]");
330 |
331 | return sb.toString();
332 | }
333 | }
334 |
--------------------------------------------------------------------------------
/src/main/java/trabe/policy/AttributeParser.java:
--------------------------------------------------------------------------------
1 | package trabe.policy;
2 |
3 | import java.text.DecimalFormat;
4 | import java.text.NumberFormat;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import java.util.Locale;
8 |
9 | import ch.hsr.geohash.*;
10 |
11 | import java.util.regex.Pattern;
12 | import java.util.regex.Matcher;
13 |
14 | import trabe.policyparser.ParseException;
15 |
16 | public class AttributeParser {
17 |
18 | private static StringBuffer getNumericalAttributeResult(String attribute, String number) {
19 | ArrayList attributes = new ArrayList();
20 | Long value = Long.valueOf(number);
21 |
22 | for (int i = 2; i <= 32; i *= 2) {
23 | attributes.add(String.format((Util.isLessThanUnsigned(value, (long) 1 << i) ? "%s_lt_2^%02d" : "%s_ge_2^%02d"), attribute, i));
24 | }
25 |
26 | for (int i = 0; i < 64; i++) {
27 | attributes.add(Util.bit_marker_flexint(attribute, i, (((long) 1 << i) & value) > 0));
28 | }
29 |
30 | attributes.add(String.format("%s_%s_%d", attribute, Util.FLEXINT_TYPE, Util.unsignedToBigInteger(value)));
31 |
32 | StringBuffer result = new StringBuffer();
33 | for (String s : attributes) {
34 | result.append(s).append(' ');
35 | }
36 | return result;
37 | }
38 | private static NumberFormat numberFormat = DecimalFormat.getInstance(Locale.ENGLISH);
39 |
40 | private static StringBuffer locationToAttributes(String attributeName, String latString, String lonString) throws ParseException {
41 | double lon;
42 | double lat;
43 | try {
44 | lon = numberFormat.parse(lonString).doubleValue();
45 | lat = numberFormat.parse(latString).doubleValue();
46 | } catch (java.text.ParseException e) {
47 | throw new ParseException("Could not parse double: "+ e.getMessage());
48 | }
49 | GeoHash hash = GeoHash.withBitPrecision(lat, lon, Util.GEOHASH_MAXBITS);
50 | List attributes = geoHashToAttributes(attributeName, hash, Util.GEOHASH_MAXBITS);
51 |
52 | StringBuffer result = new StringBuffer();
53 | for (String s : attributes) {
54 | result.append(s).append(' ');
55 | }
56 | return result;
57 | }
58 |
59 | public static List geoHashToAttributes(String attributeName, GeoHash hash, int precision) {
60 | ArrayList attributes = new ArrayList(precision);
61 | String binaryString = hash.toBinaryString();
62 | for (int i = 0; i < binaryString.length(); i++) {
63 | attributes.add(Util.bit_marker_geohash(attributeName, Util.GEOHASH_MAXBITS - i - 1, binaryString.charAt(i) == '1'));
64 | }
65 | return attributes;
66 | }
67 |
68 | private final static String name = "([a-zA-Z]\\w*)";
69 | private final static String numberInt = "(\\d+)";
70 | // *=*
71 | private final static Pattern NumbericalAttributePattern = Pattern.compile(name + "\\s*=\\s*" + numberInt);
72 | // ::
73 | private final static String numberDouble = "(\\d+[\\.]\\d*)"; // needs .
74 | private final static Pattern GeohashAttributePattern = Pattern.compile(name + ":" + numberDouble + ":" + numberDouble);
75 | public static String parseAttributes(String attributes) throws ParseException {
76 | attributes = attributes.replace(",", ".");
77 | // AttributeValue
78 | Matcher matched = NumbericalAttributePattern.matcher(attributes);
79 | StringBuffer afterNumericalAttribute = new StringBuffer();
80 | while (matched.find()) {
81 | matched.appendReplacement(afterNumericalAttribute, getNumericalAttributeResult(matched.group(1), matched.group(2)).toString());
82 | }
83 | matched.appendTail(afterNumericalAttribute);
84 |
85 | // Geohash
86 | matched = GeohashAttributePattern.matcher(afterNumericalAttribute);
87 | StringBuffer finalResult = new StringBuffer();
88 | while (matched.find()) {
89 | matched.appendReplacement(finalResult, locationToAttributes(matched.group(1), matched.group(2), matched.group(3)).toString());
90 | }
91 | matched.appendTail(finalResult);
92 | String finalResultAsString = finalResult.toString().replaceAll("\\s+", " ").trim();
93 | if (finalResultAsString.contains("=")) {
94 | throw new ParseException("Error occured while parsing attribute string: " + attributes);
95 | }
96 | return finalResultAsString;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/trabe/policy/PolicyParsing.java:
--------------------------------------------------------------------------------
1 | package trabe.policy;
2 |
3 | import java.math.BigInteger;
4 | import java.util.List;
5 |
6 | import ch.hsr.geohash.BoundingBox;
7 | import ch.hsr.geohash.GeoHash;
8 | import trabe.AbeSettings;
9 | import trabe.policyparser.*;
10 |
11 | public class PolicyParsing {
12 |
13 | private static BigInteger BI_2_64 = BigInteger.ONE.shiftLeft(64);
14 | private static BigInteger BI_2_32 = BigInteger.ONE.shiftLeft(32);
15 | private static BigInteger BI_2_16 = BigInteger.ONE.shiftLeft(16);
16 | private static BigInteger BI_2_08 = BigInteger.ONE.shiftLeft(8);
17 | private static BigInteger BI_2_04 = BigInteger.ONE.shiftLeft(4);
18 | private static BigInteger BI_2_02 = BigInteger.ONE.shiftLeft(2);
19 |
20 | public static String parsePolicy(String input) throws ParseException {
21 | try {
22 | ASTStart policy = PolicyParser.parsePolicy(input); //`.replace(",", ".")` Replacing all "," to fix locale issues
23 | return postFix(policy);
24 | } catch (TokenMgrError e) {
25 | throw new ParseException(e.getMessage());
26 | }
27 | }
28 |
29 | private static String postFix(ASTStart root) throws ParseException {
30 | return postFix_m(root).toString().trim();
31 | }
32 |
33 | private static StringBuffer postFix_m(Node current) throws ParseException {
34 | StringBuffer retVal = new StringBuffer(2000);
35 |
36 | for (int i = 0; i < current.jjtGetNumChildren(); i++) {
37 | Node child = current.jjtGetChild(i);
38 | retVal.append(postFix_m(child));
39 | }
40 |
41 | if (current instanceof ASTExpression) {
42 | handleExpression((ASTExpression) current, retVal);
43 | } else if (current instanceof ASTOf) {
44 | handleOf((ASTOf) current, retVal);
45 | } else if (current instanceof ASTAttribute) {
46 | handleAttribute((ASTAttribute) current, retVal);
47 | } else if (current instanceof ASTNumericalAttribute) {
48 | handleNumericalAttribute((ASTNumericalAttribute) current, retVal);
49 | } else if (current instanceof ASTGeoHashAttribute) {
50 | ASTGeoHashAttribute currentChild = (ASTGeoHashAttribute) current;
51 | handleGeoHashAttributeNeighbourly(currentChild, retVal);
52 | } else if (!(current instanceof ASTStart)) {
53 | throw new ParseException("Unknown node found in tree.");
54 | }
55 |
56 | return retVal.append(' ');
57 | }
58 |
59 | private static void handleGeoHashAttributeNaive(ASTGeoHashAttribute current, StringBuffer retVal) throws ParseException {
60 | if (current.getPrecision() > Util.GEOHASH_MAXBITS || current.getPrecision() <= 0) {
61 | throw new ParseException("(GeoHash precision) Only values between 1 and " + Util.GEOHASH_MAXBITS + " are supported.");
62 | }
63 | GeoHash target;
64 | try {
65 | target = GeoHash.withBitPrecision(current.getLatitude(), current.getLongitude(), current.getPrecision());
66 | } catch (IllegalArgumentException e) {
67 | throw new ParseException(e.getMessage());
68 | }
69 | handleGeoHash(target, retVal, current.getName());
70 |
71 | if (AbeSettings.DEBUG) {
72 | System.out.printf("%f,%f%n", current.getLatitude(), current.getLongitude()); // location that was initially entered
73 | printBoundingBox(target.getBoundingBox());
74 | }
75 | }
76 |
77 | private static void handleGeoHashAttributeNeighbourly(ASTGeoHashAttribute current, StringBuffer retVal) throws ParseException {
78 | if (current.getPrecision() > Util.GEOHASH_MAXBITS || current.getPrecision() <= 0) {
79 | throw new ParseException("(GeoHash precision) Only values between 1 and " + Util.GEOHASH_MAXBITS + " are supported.");
80 | }
81 | GeoHash target;
82 | try {
83 | target = GeoHash.withBitPrecision(current.getLatitude(), current.getLongitude(), current.getPrecision());
84 | } catch (IllegalArgumentException e) {
85 | throw new ParseException(e.getMessage());
86 | }
87 |
88 | GeoHash[] adjacentFields = target.getAdjacent();
89 |
90 | for (GeoHash cur : adjacentFields) {
91 | handleGeoHash(cur, retVal, current.getName());
92 | }
93 | handleGeoHash(target, retVal, current.getName());
94 | retVal.append("1of9");
95 |
96 | if (AbeSettings.DEBUG) {
97 | System.out.printf("%f,%f%n", current.getLatitude(), current.getLongitude()); // location that was initially entered
98 | printBoundingBox(target.getBoundingBox());
99 | for (GeoHash cur : adjacentFields) {
100 | printBoundingBox(cur.getBoundingBox());
101 | }
102 | }
103 | }
104 |
105 | private static void printBoundingBox(BoundingBox box) {
106 | double latError = box.getLatitudeSize() / 2;
107 | double lonError = box.getLongitudeSize() / 2;
108 |
109 | double lat = box.getCenterPoint().getLatitude();
110 | double lon = box.getCenterPoint().getLongitude();
111 | System.out.printf("%f,%f%n", lat + latError, lon - lonError); // top left
112 | System.out.printf("%f,%f%n", lat - latError, lon - lonError); // bottom left
113 | System.out.printf("%f,%f%n", lat - latError, lon + lonError); // bottom right
114 | System.out.printf("%f,%f%n", lat + latError, lon + lonError); // top right
115 | }
116 |
117 | private static void handleGeoHash(GeoHash hash, StringBuffer retVal, String attributeName) {
118 | int precision = hash.significantBits();
119 | List attributes = AttributeParser.geoHashToAttributes(attributeName, hash, precision);
120 | for (String attribute : attributes) {
121 | retVal.append(attribute).append(' ');
122 | }
123 | retVal.append(precision).append("of").append(precision).append(' ');
124 | }
125 |
126 | private static void handleAttribute(ASTAttribute current, StringBuffer retVal) throws ParseException {
127 | retVal.append(current.getName());
128 | }
129 |
130 | private static void handleNumericalAttribute(ASTNumericalAttribute current, StringBuffer retVal) throws ParseException {
131 | if (current.getValue().compareTo(BI_2_64) > 0 || current.getValue().compareTo(BigInteger.ZERO) < 0) {
132 | throw new ParseException("Only positive numbers until 2^64 are supported.");
133 | }
134 | if (current.getOp().equals("=")) {
135 | retVal.append(String.format("%s_%s_%s", current.getName(), Util.FLEXINT_TYPE, current.getValue().toString()));
136 | } else if (current.getOp().equals("<")) {
137 | handleNumericalAttribute(current.getName(), false, current.getValue(), retVal);
138 | } else if (current.getOp().equals(">")) {
139 | handleNumericalAttribute(current.getName(), true, current.getValue(), retVal);
140 | } else if (current.getOp().equals("<=")) {
141 | handleNumericalAttribute(current.getName(), false, current.getValue().add(BigInteger.ONE), retVal);
142 | } else if (current.getOp().equals(">=")) {
143 | handleNumericalAttribute(current.getName(), true, current.getValue().subtract(BigInteger.ONE), retVal);
144 | } else {
145 | throw new ParseException("Unknown comparison operator found.");
146 | }
147 | }
148 |
149 | private static void handleNumericalAttribute(String name, boolean greaterThan, BigInteger number, StringBuffer retVal) {
150 | long numberLong = number.longValue();
151 |
152 | // bit_marker_list()
153 | int bits = (number.compareTo(BI_2_32) >= 0 ? 64 :
154 | number.compareTo(BI_2_16) >= 0 ? 32 :
155 | number.compareTo(BI_2_08) >= 0 ? 16 :
156 | number.compareTo(BI_2_04) >= 0 ? 8 :
157 | number.compareTo(BI_2_02) >= 0 ? 4 : 2);
158 | int i = 0;
159 | if (greaterThan) {
160 | while (((long) 1 << i & numberLong) != 0)
161 | i++;
162 | } else {
163 | while (((long) 1 << i & numberLong) == 0)
164 | i++;
165 | }
166 |
167 | retVal.append(Util.bit_marker_flexint(name, i, greaterThan));
168 | retVal.append(' ');
169 | for (i = i + 1; i < bits; i++) {
170 | int minSatisfy;
171 | if (greaterThan) {
172 | minSatisfy = ((long) 1 << i & numberLong) != 0 ? 2 : 1;
173 | } else {
174 | minSatisfy = ((long) 1 << i & numberLong) != 0 ? 1 : 2;
175 | }
176 | retVal.append(Util.bit_marker_flexint(name, i, greaterThan));
177 | retVal.append(' ');
178 | retVal.append(minSatisfy + "of2 ");
179 | }
180 |
181 | // flexint_leader
182 | int numChildren = 0;
183 | for (int k = 2; k <= 32; k *= 2) {
184 | BigInteger bi_2_k = BigInteger.ONE.shiftLeft(k);
185 | if (greaterThan && bi_2_k.compareTo(number) > 0) {
186 | retVal.append(String.format("%s_ge_2^%02d ", name, k));
187 | numChildren++;
188 | } else if (!greaterThan && bi_2_k.compareTo(number) >= 0) {
189 | retVal.append(String.format("%s_lt_2^%02d ", name, k));
190 | numChildren++;
191 | }
192 | }
193 |
194 | int minSatisfyLeader = greaterThan ? 1 : numChildren;
195 | if (numChildren != 0) {
196 | // also part of flexint_leader
197 | retVal.append(minSatisfyLeader + "of" + numChildren);
198 | retVal.append(' ');
199 |
200 | // p = kof2_policy(gt ? 1 : 2, l, p);
201 | retVal.append((greaterThan ? 1 : 2) + "of2 ");
202 | }
203 |
204 | // delete trailing space
205 | retVal.deleteCharAt(retVal.length() - 1);
206 | }
207 |
208 | private static void handleOf(ASTOf current, StringBuffer retVal) {
209 | int numChildren = current.jjtGetNumChildren();
210 | int minSatisfy = current.getNumber();
211 | retVal.append(minSatisfy + "of" + numChildren);
212 | }
213 |
214 | private static void handleExpression(ASTExpression current, StringBuffer retVal) {
215 | int numChildren = current.jjtGetNumChildren();
216 | int minSatisfy = current.getType().equalsIgnoreCase("and") ? numChildren : 1;
217 | retVal.append(minSatisfy + "of" + numChildren);
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/main/java/trabe/policy/Util.java:
--------------------------------------------------------------------------------
1 | package trabe.policy;
2 |
3 | import java.math.BigInteger;
4 |
5 | public class Util {
6 |
7 | public static final String FLEXINT_TYPE = "flexint";
8 | public static final int FLEXINT_MAXBITS = 64;
9 |
10 | public static final String GEOHASH_TYPE = "geohash";
11 | public static final int GEOHASH_MAXBITS = 64;
12 |
13 | private static final BigInteger BI_2_64 = BigInteger.ONE.shiftLeft(64);
14 |
15 | public static BigInteger unsignedToBigInteger(long l) {
16 | final BigInteger bi = BigInteger.valueOf(l);
17 | return l >= 0 ? bi : bi.add(BI_2_64);
18 | }
19 |
20 | public static String bit_marker_flexint(String attribute, int bit, boolean on) {
21 | return bit_marker(attribute, FLEXINT_TYPE, FLEXINT_MAXBITS, bit, on);
22 | }
23 |
24 | public static String bit_marker_geohash(String attribute, int bit, boolean on) {
25 | return bit_marker(attribute, GEOHASH_TYPE, GEOHASH_MAXBITS, bit, on);
26 | }
27 |
28 | private static String bit_marker(String attribute, String type, int maxBits, int bit, boolean on) {
29 | StringBuilder result = new StringBuilder(attribute.length() + maxBits + type.length() + 2);
30 | StringBuilder bitmarks = new StringBuilder(maxBits + 1);
31 | result.append(attribute).append('_').append(type).append('_');
32 | for (int i = 0; i < maxBits; i++) {
33 | bitmarks.append('x');
34 | }
35 | bitmarks.insert(maxBits - bit, on ? '1' : '0');
36 |
37 | // delete leading x
38 | // decreasing the maxBits in the loop by one would also fix this, but that leads to
39 | // an out of bounds exception, when trying to insert with bit = 0.
40 | bitmarks.deleteCharAt(0);
41 |
42 | return result.append(bitmarks).toString();
43 | }
44 |
45 | public static boolean isLessThanUnsigned(long n1, long n2) {
46 | boolean comp = (n1 < n2);
47 | if ((n1 < 0) != (n2 < 0)) {
48 | comp = !comp;
49 | }
50 | return comp;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/resources/ASTAttribute.java:
--------------------------------------------------------------------------------
1 | package trabe.policyparser;
2 |
3 | public class ASTAttribute extends SimpleNode {
4 | private String name;
5 |
6 | public ASTAttribute(int id) {
7 | super(id);
8 | }
9 |
10 | public ASTAttribute(PolicyParser p, int id) {
11 | super(p, id);
12 | }
13 |
14 | public void setName(String name) {
15 | this.name = name;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 | public String toString() {
23 | return "Attribute: " + name;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/resources/ASTExpression.java:
--------------------------------------------------------------------------------
1 | package trabe.policyparser;
2 |
3 | public class ASTExpression extends SimpleNode {
4 | private String type = null;
5 |
6 | public ASTExpression(int id) {
7 | super(id);
8 | }
9 |
10 | public ASTExpression(PolicyParser p, int id) {
11 | super(p, id);
12 | }
13 |
14 | public void setType(String type) throws ParseException {
15 | if (this.type != null) {
16 | if (!this.type.equals(type)) throw new ParseException("Different Type already set. (Dont mix and/or without parenthesis)");
17 | } else {
18 | this.type = type;
19 | }
20 | }
21 |
22 | public String getType() {
23 | return type;
24 | }
25 |
26 | public String toString() {
27 | return "Expressiontype: " + type;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/resources/ASTGeoHashAttribute.java:
--------------------------------------------------------------------------------
1 | package trabe.policyparser;
2 |
3 | import java.text.DecimalFormat;
4 | import java.text.NumberFormat;
5 | import java.util.Locale;
6 |
7 | public class ASTGeoHashAttribute extends SimpleNode {
8 | private String name;
9 | private double lon;
10 | private double lat;
11 | private int precision;
12 | private boolean useAdjacentHashes;
13 |
14 | private static NumberFormat numberFormat = DecimalFormat.getInstance(Locale.ENGLISH);
15 |
16 | public ASTGeoHashAttribute(int id) {
17 | super(id);
18 | }
19 |
20 | public ASTGeoHashAttribute(PolicyParser p, int id) {
21 | super(p, id);
22 | }
23 |
24 | public void setValues(String name, String lon, String lat, String precision, String useAdjacentHashes) throws ParseException {
25 | this.name = name;
26 | try {
27 | this.lon = numberFormat.parse(lon).doubleValue();
28 | this.lat = numberFormat.parse(lat).doubleValue();
29 | this.useAdjacentHashes = Integer.parseInt(useAdjacentHashes) != 0;
30 | } catch (java.text.ParseException e) {
31 | throw new ParseException("Could not parse double: "+ e.getMessage());
32 | }
33 | this.precision = Integer.valueOf(precision);
34 | }
35 |
36 |
37 | public String getName() {
38 | return name;
39 | }
40 |
41 | public double getLatitude() {
42 | return lat;
43 | }
44 |
45 | public double getLongitude() {
46 | return lon;
47 | }
48 |
49 | public int getPrecision() {
50 | return precision;
51 | }
52 |
53 | public boolean useAdjacentHashes() {
54 | return useAdjacentHashes;
55 | }
56 |
57 | public String toString() {
58 | return "GeoHashAttribute: " + name + " " + lat + " " + lon + " " + precision + " " + (useAdjacentHashes ? "adjacent" : "notadjacent");
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/resources/ASTNumericalAttribute.java:
--------------------------------------------------------------------------------
1 | package trabe.policyparser;
2 |
3 | import java.math.BigInteger;
4 |
5 | public class ASTNumericalAttribute extends SimpleNode {
6 | private String name;
7 | private String op;
8 | private BigInteger value;
9 |
10 |
11 | public ASTNumericalAttribute(int id) {
12 | super(id);
13 | }
14 |
15 | public ASTNumericalAttribute(PolicyParser p, int id) {
16 | super(p, id);
17 | }
18 |
19 | public void setValues(String name, String op, String number) {
20 | this.name = name;
21 | this.op = op;
22 | this.value = new BigInteger(number);
23 | }
24 |
25 | public String getName() {
26 | return name;
27 | }
28 |
29 | public String getOp() {
30 | return op;
31 | }
32 |
33 | public BigInteger getValue() {
34 | return value;
35 | }
36 |
37 | public String toString() {
38 | return "NumericalAttribute: " + name + " " + op + " " + value;
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/resources/ASTOf.java:
--------------------------------------------------------------------------------
1 | package trabe.policyparser;
2 |
3 | public class ASTOf extends SimpleNode {
4 | private int number;
5 |
6 | public ASTOf(int id) {
7 | super(id);
8 | }
9 |
10 | public ASTOf(PolicyParser p, int id) {
11 | super(p, id);
12 | }
13 |
14 | public void setNumber(String numberString) {
15 | this.number = Integer.parseInt(numberString);
16 | }
17 |
18 | public int getNumber() {
19 | return number;
20 | }
21 |
22 | public String toString() {
23 | return "Of: " + number;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/resources/policyTree.jjt:
--------------------------------------------------------------------------------
1 | /* policy.jjt */
2 |
3 | options {
4 | STATIC = false;
5 | MULTI = true;
6 | }
7 |
8 | PARSER_BEGIN(PolicyParser)
9 | package trabe.policyparser;
10 | import java.io.Reader;
11 | import java.io.StringReader;
12 |
13 | public class PolicyParser {
14 | public static void main(String[] args) throws ParseException, TokenMgrError {
15 | PolicyParser parser = new PolicyParser( System.in );
16 | ASTStart ast = parser.Start();
17 | ast.dump("");
18 | }
19 |
20 | public static ASTStart parsePolicy(String input) throws ParseException, TokenMgrError {
21 | Reader reader = new StringReader(input);
22 | PolicyParser parser = new PolicyParser(reader);
23 | return parser.Start();
24 | }
25 | }
26 | PARSER_END(PolicyParser)
27 |
28 | SKIP : { " " | "\t" }
29 | SKIP : { "\n" | "\r" | "\r\n" }
30 |
31 | /* TOKEN : { < OPEN_PAR : "(" > } */
32 | /* TOKEN : { < CLOSE_PAR : ")" > } */
33 |
34 | TOKEN : { < OR : "or" | "OR" > }
35 | TOKEN : { < AND : "and" | "AND" > }
36 | TOKEN : { < OF : "of" | "OF" > }
37 | TOKEN : { < COMMA : "," > }
38 |
39 | TOKEN : { < OP : | | | | > }
40 | TOKEN : { < #GEQ : ">=" > }
41 | TOKEN : { < #LEQ : "<=" > }
42 | TOKEN : { < #EQ : "=" > }
43 | TOKEN : { < #LT : "<" > }
44 | TOKEN : { < #GT : ">" > }
45 |
46 | TOKEN : { < ATTNAME : ()* > }
47 | TOKEN : { < NUMBER : ()+ > }
48 | TOKEN : { < DOUBLE : ("-")?()+(".")?()* > }
49 |
50 | TOKEN : { < #LETTER : ["a"-"z", "A"-"Z"] > }
51 | TOKEN : { < #DIGIT : ["0"-"9"] > }
52 | TOKEN : { < #LETTERDIGIT : | | "_" > }
53 |
54 | ASTStart Start() :
55 | {}
56 | {
57 | Expression() (";" | )
58 | { return jjtThis; }
59 | }
60 |
61 | void Expression() #void :
62 | {
63 | Token t = null;
64 | }
65 | {
66 | (
67 | UnaryPolicy()
68 | ((t = { jjtThis.setType(t.image); }
69 | | t = { jjtThis.setType(t.image); } )
70 | UnaryPolicy())*
71 | ) #Expression(>1)
72 | }
73 |
74 | void UnaryPolicy() #void :
75 | {}
76 | {
77 | Attribute() | "(" Expression() ")" | Of()
78 | }
79 |
80 | void Of() :
81 | {
82 | Token t;
83 | }
84 | {
85 | t =
86 |
87 | "("
88 | Expression()
89 | ( Expression())*
90 | ")"
91 | { jjtThis.setNumber(t.image); }
92 |
93 | }
94 |
95 | void Attribute() #void :
96 | {
97 | Token att;
98 | }
99 | {
100 | (
101 | att =
102 | [ NumericalAttribute(att) | GeoHashAttribute(att)]
103 | { jjtThis.setName(att.image); }
104 | ) #Attribute(jjtree.nodeArity() < 1)
105 | }
106 |
107 | void NumericalAttribute(Token name) :
108 | {
109 | Token op;
110 | Token value;
111 | }
112 | {
113 | op =
114 | value =
115 | { jjtThis.setValues(name.image, op.image, value.image); }
116 | }
117 |
118 | void GeoHashAttribute(Token name) :
119 | {
120 | Token lat;
121 | Token lon;
122 | Token precision;
123 | Token approach;
124 | }
125 | {
126 | ":"
127 | lat =
128 | ":"
129 | lon =
130 | ":"
131 | precision =
132 | ":"
133 | approach =
134 | { jjtThis.setValues(name.image, lon.image, lat.image, precision.image, approach.image); }
135 | }
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/AesTest.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.io.ByteArrayInputStream;
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.IOException;
8 | import java.security.SecureRandom;
9 | import java.util.Arrays;
10 |
11 | import org.junit.BeforeClass;
12 | import org.junit.Test;
13 |
14 | import trabe.*;
15 | import trabe.aes.AesEncryption;
16 |
17 | public class AesTest {
18 |
19 | private static SecureRandom random;
20 |
21 | @BeforeClass
22 | public static void testSetup() {
23 | random = new SecureRandom();
24 | }
25 |
26 | @Test
27 | public void testStreamingAES() throws AbeEncryptionException, IOException, DecryptionException {
28 | for (int i = 0; i < 100; i++) {
29 | int plainTextLength = random.nextInt(100) + 1;
30 | byte[] plaintext = new byte[plainTextLength];
31 | byte[] cpabeKey = new byte[1000];
32 | byte[] iv = new byte[16];
33 |
34 | random.nextBytes(plaintext);
35 | random.nextBytes(cpabeKey);
36 | random.nextBytes(iv);
37 |
38 | ByteArrayInputStream encInput = new ByteArrayInputStream(plaintext);
39 | ByteArrayOutputStream encOutput = new ByteArrayOutputStream();
40 |
41 | AesEncryption.encrypt(cpabeKey, null, iv, encInput, encOutput);
42 | byte[] ciphertext = encOutput.toByteArray();
43 |
44 | ByteArrayInputStream decInput = new ByteArrayInputStream(ciphertext);
45 | ByteArrayOutputStream decOutput = new ByteArrayOutputStream();
46 | AesEncryption.decrypt(cpabeKey, null, iv, decInput, decOutput);
47 |
48 | byte[] decryptedtext = decOutput.toByteArray();
49 | assertTrue(Arrays.equals(plaintext, decryptedtext));
50 |
51 | }
52 | }
53 |
54 | @Test
55 | public void testByteArrayAES() throws AbeEncryptionException, IOException, DecryptionException {
56 | for (int i = 0; i < 100; i++) {
57 | int plainTextLength = random.nextInt(100) + 1;
58 | byte[] plaintext = new byte[plainTextLength];
59 | byte[] cpabeKey = new byte[1000];
60 | byte[] iv = new byte[16];
61 |
62 | random.nextBytes(plaintext);
63 | random.nextBytes(cpabeKey);
64 | random.nextBytes(iv);
65 |
66 | byte[] ciphertext = AesEncryption.encrypt(cpabeKey, null, iv, plaintext);
67 | byte[] decryptedPlaintext = AesEncryption.decrypt(cpabeKey, null, iv, ciphertext);
68 |
69 | assertTrue(Arrays.equals(plaintext, decryptedPlaintext));
70 | }
71 | }
72 |
73 | //@Test
74 | public void readAfterABEFileTest() throws Exception {
75 | // currently not working, difficult to do
76 | AbeSecretMasterKey smKey = Cpabe.setup();
77 | AbePublicKey pubKey = smKey.getPublicKey();
78 |
79 | int plainTextLength = random.nextInt(100) + 1;
80 | byte[] plaintext = new byte[plainTextLength];
81 | random.nextBytes(plaintext);
82 |
83 | String policy = "someAttribute1 and someAttribute2";
84 |
85 | AbeEncrypted encrypted = Cpabe.encrypt(pubKey, policy, plaintext);
86 | AbePrivateKey key = Cpabe.keygenSingle(smKey, "someAttribute1 someAttribute2");
87 |
88 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
89 | encrypted.writeEncryptedFile(baos, pubKey);
90 |
91 | byte[] encryptedData = baos.toByteArray();
92 | byte[] encryptedDataPlusBytes = Arrays.copyOf(encryptedData, encryptedData.length + 3);
93 | encryptedDataPlusBytes[encryptedDataPlusBytes.length - 1] = 15;
94 | encryptedDataPlusBytes[encryptedDataPlusBytes.length - 2] = 10;
95 | encryptedDataPlusBytes[encryptedDataPlusBytes.length - 3] = 5;
96 |
97 | ByteArrayInputStream bais = new ByteArrayInputStream(encryptedDataPlusBytes);
98 | ByteArrayOutputStream decryptedStream = new ByteArrayOutputStream();
99 | Cpabe.decrypt(key, bais, decryptedStream);
100 |
101 |
102 | byte[] decryptedData = decryptedStream.toByteArray();
103 | assertTrue(Arrays.equals(plaintext, decryptedData));
104 | assertTrue(bais.read() == 5);
105 | assertTrue(bais.read() == 10);
106 | assertTrue(bais.read() == 15);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/AllTests.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import org.junit.runners.Suite;
4 | import org.junit.runner.RunWith;
5 |
6 | @RunWith(Suite.class)
7 | @Suite.SuiteClasses({ Lw14Test.class, AesTest.class, ParserTest.class, LsssTest.class, ElementVectorTest.class, BlackBoxTest.class })
8 | public class AllTests {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/BlackBoxTest.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.BeforeClass;
6 | import org.junit.Test;
7 | import trabe.*;
8 | import trabe.policyparser.ParseException;
9 |
10 | import java.io.IOException;
11 | import java.security.SecureRandom;
12 | import java.util.Arrays;
13 |
14 | public class BlackBoxTest {
15 |
16 | private static SecureRandom random;
17 |
18 | @BeforeClass
19 | public static void testSetup() {
20 | random = new SecureRandom();
21 | }
22 |
23 | public byte[] getRandomData() {
24 | byte[] data = new byte[random.nextInt(100) + 20];
25 | random.nextBytes(data);
26 | return data;
27 | }
28 |
29 | @Test
30 | public void decryptionTest() throws IOException, AbeEncryptionException, ParseException, AbeDecryptionException {
31 | AbeSecretMasterKey smKey = Cpabe.setup(15);
32 | AbePublicKey pubKey = smKey.getPublicKey();
33 |
34 | byte[] data = getRandomData();
35 |
36 | String policy1 = "(att1 and att2) or att3";
37 |
38 | AbeEncrypted ct1 = Cpabe.encrypt(pubKey, policy1, data);
39 | AbeEncrypted ct2 = Cpabe.encrypt(pubKey, policy1, data);
40 | AbeEncrypted ct3 = Cpabe.encrypt(pubKey, policy1, data);
41 |
42 | String att1att2Attribute = "att1 att2";
43 | String att1Attribute = "att1";
44 |
45 | AbePrivateKey att1att2Key = Cpabe.keygenSingle(smKey, att1att2Attribute);
46 | AbePrivateKey att1Key = Cpabe.keygenSingle(smKey, att1Attribute);
47 |
48 | DecryptionBlackBox bb1 = new MockBlackBox(new AbePrivateKey[]{ att1att2Key, att1Key }, pubKey);
49 | DecryptionBlackBox bb2 = new MockBlackBox(new AbePrivateKey[]{ att1att2Key }, pubKey);
50 | DecryptionBlackBox bb3 = new MockBlackBox(new AbePrivateKey[]{ att1Key }, pubKey);
51 |
52 | assertTrue(Arrays.equals(data, bb1.decrypt(ct1)));
53 |
54 | assertTrue(Arrays.equals(data, bb2.decrypt(ct2)));
55 |
56 | assertNull(bb3.decrypt(ct3));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/ElementVectorTest.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import trabe.*;
4 | import trabe.lw14.Lw14;
5 | import it.unisa.dia.gas.jpbc.Element;
6 | import it.unisa.dia.gas.jpbc.Pairing;
7 | import org.junit.BeforeClass;
8 | import org.junit.Test;
9 | import trabe.lw14.Lw14Util;
10 |
11 | import java.io.File;
12 | import java.io.FileInputStream;
13 | import java.io.FileOutputStream;
14 | import java.io.IOException;
15 | import java.util.Arrays;
16 |
17 | import static org.junit.Assert.*;
18 |
19 | public class ElementVectorTest {
20 |
21 | private static Pairing p;
22 | private static AbePublicKey pub;
23 |
24 | @BeforeClass
25 | public static void setup(){
26 | AbeSecretMasterKey msk = Lw14.setup(4);
27 | p = msk.getPublicKey().getPairing();
28 | pub = msk.getPublicKey();
29 | }
30 |
31 | @Test
32 | public void createTests(){
33 | ElementVector v = new ElementVector();
34 | assertEquals(v.getDimension(), 3);
35 | assertNull(v.get(0));
36 |
37 | assertEquals(v, v);
38 |
39 | v = new ElementVector(3);
40 | assertEquals(v.getDimension(), 3);
41 | assertNull(v.get(0));
42 |
43 | v = new ElementVector(p.getZr());
44 | assertEquals(v.getDimension(), 3);
45 | assertNotNull(v.get(0));
46 |
47 | Element e = p.getZr().newRandomElement();
48 | v = new ElementVector(e, p.getZr().newRandomElement(), p.getZr().newRandomElement());
49 | assertEquals(v.getDimension(), 3);
50 | assertTrue(v.get(0).isEqual(e));
51 |
52 | Element[] ea = { p.getZr().newRandomElement(), p.getZr().newRandomElement()};
53 | v = new ElementVector(ea);
54 | assertEquals(v.getDimension(), 2);
55 | assertTrue(v.get(0).isEqual(ea[0]));
56 |
57 | v = new ElementVector(2, p.getZr());
58 | assertEquals(v.getDimension(), 2);
59 | assertNotNull(v.get(0));
60 | assertNotNull(v.get(1));
61 |
62 | int[] values = { 1, 2, 3, 4};
63 | v = new ElementVector(values, p.getZr());
64 | assertEquals(v.getDimension(), 4);
65 | assertNotNull(v.get(0));
66 | assertTrue(v.get(0).isOne());
67 | assertNotNull(v.get(1));
68 |
69 | e = p.getZr().newRandomElement();
70 | v = new ElementVector(2, e);
71 | assertEquals(v.getDimension(), 2);
72 | assertTrue(v.get(0).isEqual(e));
73 | assertTrue(v.get(1).isEqual(e));
74 | assertTrue(v.get(0) != v.get(1));
75 | }
76 |
77 | @Test
78 | public void negativeTests(){
79 | ElementVector v1 = new ElementVector(2);
80 | ElementVector v2 = new ElementVector(3);
81 |
82 | assertNotEquals(v1, v2);
83 | assertNotEquals(v1, 2);
84 | assertNotEquals(v1, null);
85 |
86 | v1 = new ElementVector(2, p.getZr());
87 | v2 = new ElementVector(2);
88 | assertNotEquals(v1, v2);
89 |
90 | v2 = v1.duplicate();
91 | v2.set(1, p.getG1().newElement()); // element of different types will be different
92 |
93 | assertNotEquals(v1, v2);
94 | }
95 |
96 | @Test
97 | public void duplicateTest() {
98 | ElementVector v = new ElementVector(2, p.getZr());
99 | ElementVector vd = v.duplicate();
100 | assertTrue(v != vd);
101 | assertTrue(v.get(0) != vd.get(0));
102 | assertTrue(v.equals(vd));
103 | }
104 |
105 | @Test
106 | public void addTest() {
107 | ElementVector v1 = new ElementVector(2, p.getZr());
108 | ElementVector v2 = new ElementVector(2, p.getZr());
109 | ElementVector result = v1.duplicate().add(v2);
110 | for(int i = 0; i < 2; i++) {
111 | assertTrue(v1.get(i).duplicate().add(v2.get(i)).isEqual(result.get(i)));
112 | }
113 |
114 | v1.add(v2);
115 | for(int i = 0; i < 2; i++) {
116 | assertTrue(v1.get(i).isEqual(result.get(i)));
117 | }
118 | }
119 |
120 | @Test
121 | public void mulTest() {
122 | ElementVector v1 = new ElementVector(2, p.getZr());
123 | ElementVector v2 = new ElementVector(2, p.getZr());
124 | ElementVector result = v1.duplicate().mul(v2);
125 | for(int i = 0; i < 2; i++) {
126 | assertTrue(v1.get(i).duplicate().mul(v2.get(i)).isEqual(result.get(i)));
127 | }
128 |
129 | v1.mul(v2);
130 | for(int i = 0; i < 2; i++) {
131 | assertTrue(v1.get(i).isEqual(result.get(i)));
132 | }
133 |
134 | Element e = p.getZr().newRandomElement();
135 | ElementVector result2 = v1.duplicate().mul(e);
136 | for(int i = 0; i < 2; i++) {
137 | assertTrue(v1.get(i).duplicate().mul(e).isEqual(result2.get(i)));
138 | }
139 | }
140 |
141 | @Test
142 | public void sumTest() {
143 | int[] values = { 1, 2, 0};
144 | ElementVector v = new ElementVector(values, p.getZr());
145 | ElementVector vd = v.duplicate();
146 | Element result = v.sum();
147 | assertTrue(result.isEqual(p.getZr().newElement(3)));
148 |
149 | // non-overwriting:
150 | assertTrue(v.equals(vd));
151 | }
152 |
153 | @Test
154 | public void scalarTest() {
155 | int[] values1 = { 1, 2, 0};
156 | int[] values2 = { 0, 1, 5};
157 | ElementVector v1 = new ElementVector(values1, p.getZr());
158 | ElementVector v1d = v1.duplicate();
159 | ElementVector v2 = new ElementVector(values2, p.getZr());
160 | Element result = v1.scalar(v2);
161 | assertTrue(result.isEqual(p.getZr().newElement(2)));
162 |
163 | // non-overwriting:
164 | assertTrue(v1.equals(v1d));
165 | }
166 |
167 | @Test
168 | public void powTest() {
169 | ElementVector v = new ElementVector(2, p.getZr());
170 | ElementVector vd = v.duplicate();
171 |
172 | Element e = p.getZr().newRandomElement();
173 | Element ed = e.duplicate();
174 | ElementVector result = v.powInBase(e);
175 | for(int i = 0; i < 2; i++) {
176 | assertTrue(e.duplicate().powZn(v.get(i)).isEqual(result.get(i)));
177 | }
178 |
179 | assertTrue(v.equals(vd));
180 | assertTrue(v != vd);
181 | assertTrue(e.equals(ed));
182 | assertTrue(e != ed);
183 | }
184 |
185 | @Test
186 | public void readWriteTest() throws IOException {
187 | File folder = TestUtil.prepareTestFolder();
188 | File file = new File(folder, "eVec_out.dat");
189 |
190 | ElementVector v = new ElementVector(6, p.getZr());
191 | AbeOutputStream os = new AbeOutputStream(new FileOutputStream(file), pub);
192 | v.writeToStream(os);
193 | os.flush();
194 | os.close();
195 |
196 | AbeInputStream is = new AbeInputStream(new FileInputStream(file), pub);
197 | ElementVector rv = ElementVector.readFromStream(is);
198 | is.close();
199 |
200 | assertNotNull(rv);
201 | assertEquals(v, rv);
202 | }
203 |
204 | @Test
205 | public void readWriteArrayTest() throws IOException {
206 | File folder = TestUtil.prepareTestFolder();
207 | File file = new File(folder, "eVecArray_out.dat");
208 |
209 | ElementVector[] vArray = new ElementVector[10];
210 | for(int i = 0; i < 10; i++) {
211 | vArray[i] = new ElementVector(6, p.getZr());
212 | }
213 |
214 | AbeOutputStream os = new AbeOutputStream(new FileOutputStream(file), pub);
215 | Lw14Util.writeArray(vArray, os);
216 | os.flush();
217 | os.close();
218 |
219 | AbeInputStream is = new AbeInputStream(new FileInputStream(file), pub);
220 | ElementVector[] rvArray = Lw14Util.readElementVectorArray(is);
221 | is.close();
222 |
223 | assertNotNull(rvArray);
224 | assertTrue(Arrays.equals(vArray, rvArray));
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/LsssTest.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import trabe.AbePublicKey;
6 | import trabe.AbeSecretMasterKey;
7 | import trabe.ElementVector;
8 | import trabe.lw14.Lw14;
9 | import trabe.lw14.policy.LsssMatrix;
10 | import it.unisa.dia.gas.jpbc.Element;
11 | import it.unisa.dia.gas.jpbc.Field;
12 | import org.junit.Test;
13 |
14 | import java.math.BigInteger;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 |
18 | public class LsssTest {
19 |
20 | @Test
21 | public void testExampleLsssPolicy() throws Exception{
22 | // the test data comes from http://eprint.iacr.org/2010/351
23 | String p = "a and (d or (b and c))";
24 | int[][] expectedMatrix = {
25 | { 1, 1, 0 },
26 | { 0, -1, 1 },
27 | { 0, 0, -1 },
28 | { 0, -1, 0 }};
29 |
30 | AbeSecretMasterKey msk = Lw14.setup(4);
31 | AbePublicKey pub = msk.getPublicKey();
32 |
33 | LsssMatrix matrix = LsssMatrix.createMatrixFromBooleanFormula(p, pub);
34 |
35 | assertEquals(4, matrix.getAttributes());
36 | assertEquals(3, matrix.getColumns());
37 |
38 | int i = 0;
39 | for(int[] row : expectedMatrix) {
40 | int j = 0;
41 | for(int value : row) {
42 | assertEquals(matrix.get(i, j).value, value);
43 | j++;
44 | }
45 | i++;
46 | }
47 | }
48 |
49 | @Test
50 | public void testExampleThresholdLsssPolicy() throws Exception{
51 | HashMap matrixesForPolicies = new HashMap(3);
52 |
53 | matrixesForPolicies.put("a and b and c", new Integer[][]{
54 | { 1, 1, 1 },
55 | { 1, 2, 4 },
56 | { 1, 3, 9 },
57 | });
58 | matrixesForPolicies.put("a or b or c", new Integer[][]{
59 | { 1 },
60 | { 1 },
61 | { 1 },
62 | });
63 | matrixesForPolicies.put("d or (a and b and c) or e", new Integer[][]{
64 | { 1, 0, 0 },
65 | { 1, 1, 1 },
66 | { 1, 2, 4 },
67 | { 1, 3, 9 },
68 | { 1, 0, 0 },
69 | });
70 | matrixesForPolicies.put("d and (a or b or c) and e", new Integer[][]{
71 | { 1, 1, 1 },
72 | { 1, 2, 4 },
73 | { 1, 2, 4 },
74 | { 1, 2, 4 },
75 | { 1, 3, 9 },
76 | });
77 | matrixesForPolicies.put("d and 1 of (a, b, c) and e", new Integer[][]{
78 | { 1, 1, 1 },
79 | { 1, 2, 4 },
80 | { 1, 2, 4 },
81 | { 1, 2, 4 },
82 | { 1, 3, 9 },
83 | });
84 | matrixesForPolicies.put("d and 2 of (a, b, c) and e", new Integer[][]{
85 | { 1, 1, 1, 0 },
86 | { 1, 2, 4, 1 },
87 | { 1, 2, 4, 2 },
88 | { 1, 2, 4, 3 },
89 | { 1, 3, 9, 0 },
90 | });
91 | matrixesForPolicies.put("3 of (a, b, c, d)", new Integer[][]{
92 | { 1, 1, 1 },
93 | { 1, 2, 4 },
94 | { 1, 3, 9 },
95 | { 1, 4, 16 },
96 | });
97 | matrixesForPolicies.put("3 of (e, f, g, 3 of (a, b, c, d))", new Integer[][]{
98 | { 1, 1, 1, 0, 0 },
99 | { 1, 2, 4, 0, 0 },
100 | { 1, 3, 9, 0, 0 },
101 | { 1, 4, 16, 1, 1 },
102 | { 1, 4, 16, 2, 4 },
103 | { 1, 4, 16, 3, 9 },
104 | { 1, 4, 16, 4, 16 },
105 | });
106 | matrixesForPolicies.put("2 of (a, 2 of (c, d, e), b)", new Integer[][]{
107 | { 1, 1, 0 },
108 | { 1, 2, 1 },
109 | { 1, 2, 2 },
110 | { 1, 2, 3 },
111 | { 1, 3, 0 },
112 | });
113 | matrixesForPolicies.put("2 of (a, 3 of (c, d, e), b)", new Integer[][]{
114 | { 1, 1, 0, 0 },
115 | { 1, 2, 1, 1 },
116 | { 1, 2, 2, 4 },
117 | { 1, 2, 3, 9 },
118 | { 1, 3, 0, 0 },
119 | });
120 | matrixesForPolicies.put("1 of (a, 1 of (c, d, e), b)", new Integer[][]{
121 | { 1 },
122 | { 1 },
123 | { 1 },
124 | { 1 },
125 | { 1 },
126 | });
127 |
128 |
129 | AbeSecretMasterKey msk = Lw14.setup(4);
130 | AbePublicKey pub = msk.getPublicKey();
131 | Field zR = pub.getPairing().getZr();
132 |
133 | LsssMatrix matrix;
134 | Integer[][] expectedMatrix;
135 | Integer[] expectedRow;
136 | for(Map.Entry e : matrixesForPolicies.entrySet()) {
137 | matrix = LsssMatrix.createMatrixFromThresholdFormula(e.getKey(), pub);
138 | expectedMatrix = e.getValue();
139 | assertEquals(matrix.getAttributes(), expectedMatrix.length);
140 | for(int i = 0; i < expectedMatrix.length; i++) {
141 | expectedRow = expectedMatrix[i];
142 | assertEquals(matrix.getColumns(), expectedRow.length);
143 | for(int j = 0; j < expectedRow.length; j++) {
144 | assertEquals((Integer)matrix.get(i, j).value, expectedRow[j]);
145 | }
146 | }
147 | }
148 | }
149 |
150 | @Test
151 | public void testElementVectorFromLsssPolicy() throws Exception{
152 | // the test data comes from http://eprint.iacr.org/2010/351
153 | String p = "a and (d or (b and c))";
154 | int[][] expectedMatrix = {
155 | { 1, 1, 0 },
156 | { 0, -1, 1 },
157 | { 0, 0, -1 },
158 | { 0, -1, 0 }};
159 |
160 | AbeSecretMasterKey msk = Lw14.setup(4);
161 | AbePublicKey pub = msk.getPublicKey();
162 |
163 | LsssMatrix matrix = LsssMatrix.createMatrixFromBooleanFormula(p, pub);
164 |
165 | assertEquals(4, matrix.getAttributes());
166 | assertEquals(3, matrix.getColumns());
167 |
168 | Field zr = pub.getPairing().getZr();
169 |
170 | for (int row = 0; row < matrix.getAttributes(); row++) {
171 | ElementVector ev = matrix.getAttributeRow(row, zr);
172 | assertEquals(ev.getDimension(), matrix.getColumns());
173 | for(int cell = 0; cell < ev.getDimension(); cell++) {
174 | Element expectedValue = zr.newElement(expectedMatrix[row][cell]);
175 | assertTrue(expectedValue.isEqual(ev.get(cell)));
176 | }
177 | }
178 |
179 | int i = 0;
180 | for(int[] row : expectedMatrix) {
181 | ElementVector v = ElementVector.createFrom(matrix, i, pub.getPairing().getZr());
182 | int j = 0;
183 | for(int value : row) {
184 | assertTrue(v.get(j).isEqual(pub.getPairing().getZr().newElement(value)));
185 | j++;
186 | }
187 | i++;
188 | }
189 | }
190 |
191 | @Test
192 | public void testElementPowerMinusOne() throws Exception{
193 | AbeSecretMasterKey msk = Lw14.setup(4);
194 | AbePublicKey pub = msk.getPublicKey();
195 |
196 | Field zr = pub.getPairing().getZr();
197 | Field gt = pub.getPairing().getGT();
198 |
199 | Element t1 = gt.newRandomElement();
200 | Element minusOne = zr.newElement(BigInteger.valueOf(-1));
201 |
202 | // System.out.println("t: " + t1);
203 | // System.out.println("-1: " + minusOne);
204 |
205 | Element halfMinusOne = minusOne.duplicate().div(zr.newElement(BigInteger.valueOf(2)));
206 |
207 | Element tPowMinusOne = t1.duplicate().powZn(minusOne);
208 | Element tPowHalfMinusOneMulTPowHalfMinusOne = t1.duplicate().powZn(halfMinusOne).mul(t1.duplicate().powZn(halfMinusOne));
209 |
210 | // System.out.println("-1/2: " + halfMinusOne);
211 | // System.out.println("t^{-1}: " + tPowMinusOne);
212 | // System.out.println("t^{-1/2}*t^{-1/2}: " + tPowHalfMinusOneMulTPowHalfMinusOne);
213 |
214 | assertEquals(tPowMinusOne, tPowHalfMinusOneMulTPowHalfMinusOne);
215 | }
216 |
217 | /*
218 | @Test
219 | public void testWkGeneration() throws Exception{
220 | // the test data comes from http://eprint.iacr.org/2010/351
221 | String p = "a and (d or (b and c))";
222 | int[][] baseMatrix = {
223 | { 1, 1, 0 },
224 | { 0, -1, 1 },
225 | { 0, 0, -1 },
226 | { 0, -1, 0 }};
227 | int[][] transposed = {
228 | { 1, 0, 0, 0 },
229 | { 1, -1, 0, -1 },
230 | { 0, 1, -1, 0 }};
231 | int[][] transposedABC = {
232 | { 1, 0, 0 },
233 | { 1, -1, 0 },
234 | { 0, 1, -1 }};
235 | int[][] transposedABD = {
236 | { 1, 0, 0 },
237 | { 1, -1, -1 },
238 | { 0, 1, 0 }};
239 | int[][] transposedACD = {
240 | { 1, 0, 0 },
241 | { 1, 0, -1 },
242 | { 0, -1, 0 }};
243 | int[][] transposedBCD = {
244 | { 0, 0, 0 },
245 | { -1, 0, -1 },
246 | { 1, -1, 0 }};
247 |
248 | int[][] andMatrix = {
249 | { 0, 0, 0, 1 },
250 | { -1, 0, 0, 1 },
251 | { 0, -1, 0, 1 },
252 | { 0, -0, -1, 1 }};
253 |
254 | int[][] matrix = andMatrix;
255 |
256 | AbeSecretMasterKey msk = Lw14.setup(4);
257 | AbePublicKey pub = msk.getPublicKey();
258 | Field zr = pub.getPairing().getZr();
259 | ElementField ef = new ElementField(zr);
260 |
261 | Matrix mat = new Matrix(matrix.length, matrix[0].length, ef);
262 |
263 | int i = 0;
264 | for(int[] row : matrix) {
265 | int j = 0;
266 | for(int value : row) {
267 | mat.set(i, j, zr.newElement(value));
268 | j++;
269 | }
270 | i++;
271 | }
272 |
273 | //mat.invert();
274 | mat.reducedRowEchelonForm();
275 |
276 | for (i = 0; i < mat.rowCount(); i++) {
277 | for (int j = 0; j < mat.columnCount(); j++) {
278 | if (j > 0)
279 | System.out.print(" ");
280 | System.out.print(mat.get(i, j));
281 | }
282 | System.out.println();
283 | }
284 | }
285 | */
286 | }
287 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/ParserTest.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import static org.junit.Assert.*;
4 | import trabe.policy.*;
5 | import trabe.policyparser.ParseException;
6 |
7 | import org.junit.Test;
8 |
9 | public class ParserTest {
10 |
11 | @Test
12 | @SuppressWarnings("unused")
13 | public void testPolicyParser() throws ParseException {
14 | // String policyInput = "a or (b > 5 and a:52.52001:13.40495:22 and 3 of (1 of (c, d, e),x,y))";
15 | String policyInput = "a:52.52001:13.40495:32:1";
16 | //ASTStart policyTree = PolicyParser.parsePolicy(policyInput);
17 | //policyTree.dump("");
18 | String parsedPolicy = PolicyParsing.parsePolicy(policyInput);
19 | //System.out.println("Parsed policy:\n" + parsedPolicy);
20 | // TODO check if parsed policy is correct
21 | }
22 |
23 | @Test //TODO finish writing test
24 | public void testAttributeParser() throws ParseException {
25 | //String attributes4 = "att1:52.52001:13.40495";
26 | //String parsed4 = AttributeParser.parseAttributes(attributes4);
27 | }
28 |
29 | @Test
30 | public void attributeParserWhitespaceTest() throws ParseException {
31 | String attributes1 = "att1 att2";
32 | String attributes2 = "att1\t\n\f\r\t\tatt2";
33 |
34 | String parsed1 = AttributeParser.parseAttributes(attributes1);
35 | String parsed2 = AttributeParser.parseAttributes(attributes2);
36 |
37 | assertEquals(parsed1, "att1 att2");
38 | assertEquals(parsed2, "att1 att2");
39 | }
40 |
41 |
42 | @Test(expected=ParseException.class)
43 | public void attributeParserInvalidNumberTest() throws ParseException {
44 | System.out.println("Parsed as: " + AttributeParser.parseAttributes("att1 = -5"));
45 | }
46 |
47 | @Test(expected=ParseException.class)
48 | public void attributeParserEqualSignTest() throws ParseException {
49 | System.out.println("Parsed as: " + AttributeParser.parseAttributes("att1 = test"));
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/TestUtil.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import java.io.*;
4 | import java.security.SecureRandom;
5 | import java.util.UUID;
6 |
7 | public class TestUtil {
8 | private static String testPath = "testFolder";
9 |
10 | private static SecureRandom random = new SecureRandom();
11 |
12 | /**
13 | * Generates a new test folder if it is not yet available and return it.
14 | * @return Old or newly created test folder
15 | */
16 | public static File prepareTestFolder() throws IOException {
17 | File f = new File(testPath);
18 | if (!f.exists() && !f.mkdirs()) {
19 | throw new IOException("Test folder could not be created");
20 | }
21 | return f;
22 | }
23 |
24 | /**
25 | * Creates a randomly named file and fills it with random data.
26 | *
27 | * @param bytes Number of random bytes in the file
28 | * @return Created file
29 | * @throws IOException
30 | */
31 | public static File randomData(int bytes) throws IOException{
32 | byte[] data = new byte[bytes];
33 | random.nextBytes(data);
34 | File randomFile = new File(testPath, UUID.randomUUID().toString()+".dat");
35 | FileOutputStream fos = new FileOutputStream(randomFile);
36 | fos.write(data);
37 | fos.flush();
38 | fos.close();
39 | return randomFile;
40 | }
41 |
42 | /**
43 | * Creates a randomly named file and fills it with random data.
44 | *
45 | * @return Created file
46 | * @throws IOException
47 | */
48 | public static File randomData() throws IOException{
49 | return randomData(125);
50 | }
51 |
52 | public static byte[] read(File f) throws IOException {
53 | FileInputStream fis = new FileInputStream(f);
54 | byte[] b = new byte[(int) f.length()];
55 | fis.read(b);
56 | fis.close();
57 | return b;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/test/java/trabe/tests/WeberTest.java:
--------------------------------------------------------------------------------
1 | package trabe.tests;
2 |
3 | import static org.junit.Assert.assertFalse;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.security.SecureRandom;
7 | import java.util.Arrays;
8 |
9 | import org.junit.BeforeClass;
10 |
11 | import trabe.AbeEncrypted;
12 | import trabe.AbePrivateKey;
13 | import trabe.AbePublicKey;
14 | import trabe.AbeSecretMasterKey;
15 | import trabe.Cpabe;
16 | import trabe.CpabeWeber;
17 |
18 | public class WeberTest {
19 | private static SecureRandom random;
20 |
21 | @BeforeClass
22 | public static void testSetup() {
23 | random = new SecureRandom();
24 | }
25 |
26 | public byte[] getRandomData() {
27 | byte[] data = new byte[random.nextInt(100) + 20];
28 | random.nextBytes(data);
29 | return data;
30 | }
31 |
32 | // so we dont need to check for exceptions every time we want to decrypt
33 | private byte[] decrypt(AbePrivateKey privateKey, AbeEncrypted encryptedData, byte[] lbeKey) {
34 | try {
35 | return CpabeWeber.decrypt(privateKey, encryptedData, lbeKey);
36 | } catch (Exception e) {
37 | return null;
38 | }
39 | }
40 |
41 | //@Test
42 | public void numberTest() throws Exception {
43 | AbeSecretMasterKey smKey = CpabeWeber.setup();
44 | AbePublicKey pubKey = smKey.getPublicKey();
45 |
46 | byte[] data = getRandomData();
47 | String policy = "trivial and to and decrypt";
48 |
49 | byte[] lbeKey1 = new byte[16];
50 | random.nextBytes(lbeKey1);
51 |
52 | byte[] lbeKey2 = new byte[16];
53 | random.nextBytes(lbeKey2);
54 |
55 | // each AbeEncrypted can only be decrypted once, since we advance the stream to after the AES data.
56 | AbeEncrypted withFirstLbeKey1 = CpabeWeber.encrypt(pubKey, policy, data, lbeKey1);
57 | AbeEncrypted withFirstLbeKey2 = CpabeWeber.encrypt(pubKey, policy, data, lbeKey1);
58 | AbeEncrypted withSecondLbeKey1 = CpabeWeber.encrypt(pubKey, policy, data, lbeKey2);
59 | AbeEncrypted withSecondLbeKey2 = CpabeWeber.encrypt(pubKey, policy, data, lbeKey2);
60 |
61 | String allAttributes = "trivial to decrypt";
62 | AbePrivateKey allKey = Cpabe.keygenSingle(smKey, allAttributes);
63 |
64 | assertTrue(Arrays.equals(data, decrypt(allKey, withFirstLbeKey1, lbeKey1)));
65 | assertFalse(Arrays.equals(data, decrypt(allKey, withFirstLbeKey2, lbeKey2)));
66 | assertFalse(Arrays.equals(data, decrypt(allKey, withSecondLbeKey1, lbeKey1)));
67 | assertTrue(Arrays.equals(data, decrypt(allKey, withSecondLbeKey2, lbeKey2)));
68 | }
69 | }
70 |
--------------------------------------------------------------------------------