FNR Cipher is a Java implementation for Flexible Naor and Reingold encryption scheme.
It's simple. If you give an integer, you get a encrypted integer. This is two-way operation. That means, if you give the encrypted integer also you get the original integer. The FNR algorithm preserves your data size, no expand, no shrink. All operation space limited by key bit length.
This method also known as format preserving encryption. FNR algorithm is useful for small data types (up to 128 bits) such as credit card or user ids.
FNR uses AES-128 internally in each encryption/decryption rounds. FNR Java contains optimized and minimal AES-128 pure Java cipher. It's may be prefer instead of Java Cryptography Extension in case of performance considerations or JVM limitations. This library doesn't have any dependencies and it is fit for limited envorinments like Andorid. (The JAR file only 43kb.)
The FNR Java library is binary compatible with reference C implementation.
FNR Java provides some built-in codecs for basic data types encryption.
Java Type | Codec | Notes |
---|---|---|
Byte | FNRCodec.BYTE | NP_SIGN codec not preserve sign. |
Short | FNRCodec.SHORT | NP_SIGN codec not preserve sign. |
Character | FNRCodec.CHAR | NP_SIGN codec not preserve sign. |
Integer | FNRCodec.INT | NP_SIGN codec not preserve sign. |
Float | FNRCodec.FLOAT | NP_SIGN_EXP codec not preserve sign and exponent. |
Long | FNRCodec.LONG | NP_SIGN codec not preserve sign. |
Double | FNRCodec.DOUBLE | NP_SIGN_EXP codec not preserve sign and exponent. |
BigInteger | FNRCodec.BIGINT_128 | The acceptable value range are -2^127 to 2^127-1 or 0 to 2^128-1 |
Date | FNRCodec.DATE | - |
Inet4Address | FNRCodec.IPV4 | - |
Inet6Address | FNRCodec.IPV6 |
Note: All numeric codecs run as litte-endian for compatibiliy with other platform like C or Go and preserve sign and exponents as default.
<dependency>
<groupId>io.octa.security</groupId>
<artifactId>fnr</artifactId>
<version>1.0.1</version>
</dependency>
String passphrase = "this is a password";
String salt = "this is a salt value"; // for built-in PBKDF2 key generation.
byte[] aesKey = FNRUtils.createAes128KeyWithPBKDF2(passphrase, salt);
// Integer encryption
FNRKey key = new FNRKey(aesKey, FNRCodec.INT.getRequiredKeyNumBits());
FNRTweak tweak = key.generateTweak("this is a tweak value");
int raw = 42;
int encrypted = FNRCipher.encrypt(FNRCodec.INT, key, tweak, raw);
int decrypted = FNRCipher.decrypt(FNRCodec.INT, key, tweak, encrypted);
System.out.println("raw: " + raw); // prints 42
System.out.println("encrypted: " + encrypted); // prints 1432569698
System.out.println("decrypted: " + decrypted); // prints 42
// IP encryption
key = new FNRKey(aesKey, FNRCodec.IPV4.getRequiredKeyNumBits());
tweak = key.generateTweak("this is a tweak value");
Inet4Address rawIP = (Inet4Address) Inet4Address.getByName("8.4.4.2");
Inet4Address encryptedIP = FNRCipher.encrypt(FNRCodec.IPV4, key, tweak, rawIP);
Inet4Address decryptedIP = FNRCipher.decrypt(FNRCodec.IPV4, key, tweak, encryptedIP);
System.out.println("raw: " + rawIP); // prints 8.4.4.2
System.out.println("encrypted: " + encryptedIP); // prints 25.123.159.248
System.out.println("decrypted: " + decryptedIP); // prints 8.4.4.2
Library | AES Encryption Method | Encryption | Decryption | Notes |
---|---|---|---|---|
Reference C implementaion | OpenSSL | 229141.720 ops/s | 230386.135 ops/s | OpenSSL uses CPU AES Extension |
FNR Java | Built-In | 198160.740 ops/s | 202775.251 ops/s | AES encryption with built-in minimal, optimized cipher |
Java binding for Reference C implementaion | OpenSSL | 105766.458 ops/s | 106495.132 ops/s | I think the cause of bottleneck is JNI round-trip overhead. |
FNR Java | JCE | 82998.094 ops/s | 81175.897 ops/s | AES encryption with standard Java Cryptography Extension |
Tested on Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz.
Java Benchmark: FNRCipherBenchmarkTest.java
JMH 1.11.3 (released 3 days ago) VM version: JDK 1.8.0_66, VM 25.66-b17 VM invoker: /usr/lib/jvm/java-8-oracle/jre/bin/java VM options: <none> Warmup: 5 iterations, 1 s each Measurement: 5 iterations, 1 s each Timeout: 10 min per iteration Threads: 1 thread, will synchronize iterations Benchmark mode: Throughput, ops/time
C Benchmark: bench.c
GCC v5.2.1 compiles with -O2 and use OpenSSL 1.0.2d
FNR is designed by Sashank Dara ([email protected]), Scott Fluhrer ([email protected]).
Java implementation was written by Mehmet Gurevin ([email protected])
Copyright (c) 2015-2016, Octabase, Ltd. All Rights Reserved.