├── .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 | *
  1. 0 is an element of the field, and 0 + x = x. (Existence of additive identity)
  2. 15 | *
  3. 1 is an element of the field, and 1 * x = x. (Existence of multiplicative identity)
  4. 16 | *
  5. 0 ≠ 1. (Distinctness of additive and multiplicative identities)
  6. 17 | *
  7. x + y = y + x. (Commutativity of addition)
  8. 18 | *
  9. x * y = y * x. (Commutativity of multiplication)
  10. 19 | *
  11. (x + y) + z = x + (y + z). (Associativity of addition)
  12. 20 | *
  13. (x * y) * z = x * (y * z). (Associativity of multiplication)
  14. 21 | *
  15. x * (y + z) = (x * y) + (x * z). (Distributivity of multiplication over addition)
  16. 22 | *
  17. x is an element of the field, such that x + (−x) = 0. (Existence of additive inverse)
  18. 23 | *
  19. x−1 is an element of the field, such that x * (x−1) = 1. (Existence of multiplicative inverse)
  20. 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 | --------------------------------------------------------------------------------