├── .gitignore ├── scripts ├── version.sh └── build.sh ├── .travis.yml ├── src ├── main │ └── java │ │ └── org │ │ └── abstractj │ │ └── kalium │ │ ├── keys │ │ ├── Key.java │ │ ├── PublicKey.java │ │ ├── PrivateKey.java │ │ ├── VerifyKey.java │ │ ├── KeyPair.java │ │ ├── AuthenticationKey.java │ │ └── SigningKey.java │ │ ├── encoders │ │ ├── Raw.java │ │ ├── Encoder.java │ │ └── Hex.java │ │ ├── crypto │ │ ├── Random.java │ │ ├── Advanced.java │ │ ├── ShortHash.java │ │ ├── Password.java │ │ ├── SealedBox.java │ │ ├── Point.java │ │ ├── Util.java │ │ ├── SecretBox.java │ │ ├── Hash.java │ │ ├── Aead.java │ │ └── Box.java │ │ └── NaCl.java └── test │ └── java │ └── org │ └── abstractj │ └── kalium │ ├── crypto │ ├── UtilTest.java │ ├── RandomTest.java │ ├── AeadTest.java │ ├── ShortHashTest.java │ ├── PointTest.java │ ├── SealedBoxTest.java │ ├── SecretBoxTest.java │ ├── AdvancedTest.java │ ├── PasswordTest.java │ ├── BoxTest.java │ └── HashTest.java │ ├── encoders │ └── RawTest.java │ ├── keys │ ├── VerifyKeyTest.java │ ├── SigningKeyTest.java │ ├── KeyPairTest.java │ └── AuthenticationKeyTest.java │ └── fixture │ └── TestVectors.java ├── appveyor.yml ├── README.md ├── pom.xml └── LICENSE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | target/ 4 | -------------------------------------------------------------------------------- /scripts/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export LIBSODIUM=`curl -s https://download.libsodium.org/libsodium/releases/ | sed -e 's/<[^>]*>//g' | grep -i stable | awk '{print $1}' | tail -n2 | grep -v "minisig"` 4 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . scripts/version.sh 4 | 5 | wget -c https://download.libsodium.org/libsodium/releases/$LIBSODIUM 6 | tar xzvf $LIBSODIUM 7 | cd libsodium-stable && mkdir vendor 8 | ./configure --prefix=`pwd`/vendor 9 | make && make install 10 | cd ../ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | before_script: 4 | - ./scripts/build.sh 5 | 6 | script: 7 | - export LD_LIBRARY_PATH="/home/travis/build/abstractj/kalium/libsodium-stable/vendor/lib" 8 | - mvn clean install 9 | 10 | env: JAVA_OPTS="-Djava.library.path=/home/travis/build/abstractj/kalium/libsodium-stable/vendor/lib" 11 | 12 | jdk: 13 | - oraclejdk8 14 | - oraclejdk9 15 | - openjdk7 16 | - openjdk8 17 | 18 | after_success: 19 | - rm -rf libsodium-stable* 20 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/Key.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.keys; 2 | 3 | import static org.abstractj.kalium.encoders.Encoder.HEX; 4 | 5 | /** 6 | * Copyright 2013 Bruno Oliveira, and individual contributors 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | public interface Key { 21 | byte[] toBytes(); 22 | } 23 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | os: Windows Server 2012 3 | install: 4 | - cmd: SET JAVA_HOME=C:\Program Files (x86)\Java\jdk1.8.0 5 | - cmd: SET LIBSODIUM_VERSION=1.0.3 6 | - ps: | 7 | Add-Type -AssemblyName System.IO.Compression.FileSystem 8 | if (!(Test-Path -Path "C:\libsodium" )) { 9 | (New-Object System.Net.WebClient).DownloadFile( 10 | "https://github.com/jedisct1/libsodium/archive/$env:LIBSODIUM_VERSION.zip", 11 | 'C:\libsodium.zip' 12 | ) 13 | [System.IO.Compression.ZipFile]::ExtractToDirectory("C:\libsodium.zip", "C:\") 14 | Rename-Item C:\libsodium-$env:LIBSODIUM_VERSION C:\libsodium 15 | } 16 | - cmd: msbuild C:\libsodium\libsodium.vcxproj /property:Configuration=ReleaseDLL /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 17 | - cmd: SET PATH=C:\libsodium\Build\ReleaseDLL\Win32;%PATH% 18 | build_script: 19 | - mvn clean install -q --batch-mode -DargLine=-Dfile.encoding=UTF-8 20 | cache: 21 | - C:\libsodium 22 | - C:\Users\appveyor\.m2 23 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/encoders/Raw.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.encoders; 18 | 19 | public class Raw implements Encoder { 20 | 21 | public byte[] decode(final String data) { 22 | return data != null ? data.getBytes(CHARSET) : null; 23 | } 24 | 25 | @Override 26 | public String encode(byte[] data) { 27 | return data != null ? new String(data, CHARSET) : null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/encoders/Encoder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.encoders; 18 | 19 | import java.nio.charset.Charset; 20 | 21 | public interface Encoder { 22 | 23 | public static final Charset CHARSET = Charset.forName("US-ASCII"); 24 | 25 | public static final Hex HEX = new Hex(); 26 | public static final Raw RAW = new Raw(); 27 | 28 | public byte[] decode(String data); 29 | 30 | public String encode(final byte[] data); 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/UtilTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | public class UtilTest { 23 | @Test 24 | public void testPrependZeros() throws Exception { 25 | byte[] src = {'t', 'e', 's', 't'}; 26 | byte[] result = Util.prependZeros(3, src); 27 | Assert.assertArrayEquals(new byte[]{0, 0, 0, 't', 'e', 's', 't'}, result); 28 | } 29 | 30 | @Test(expected = RuntimeException.class) 31 | public void testDataNull() { 32 | Util.checkLength(null, 3); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Random.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import static org.abstractj.kalium.NaCl.sodium; 20 | 21 | public class Random { 22 | 23 | private static final int DEFAULT_SIZE = 32; 24 | 25 | /** 26 | * Generate random bytes 27 | * 28 | * @param n number or random bytes 29 | * @return 30 | */ 31 | public byte[] randomBytes(int n) { 32 | byte[] buffer = new byte[n]; 33 | sodium().randombytes(buffer, n); 34 | return buffer; 35 | } 36 | 37 | public byte[] randomBytes() { 38 | byte[] buffer = new byte[DEFAULT_SIZE]; 39 | sodium().randombytes(buffer, DEFAULT_SIZE); 40 | return buffer; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Advanced.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.abstractj.kalium.crypto; 17 | 18 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_STREAM_KEYBYTES; 19 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_STREAM_NONCEBYTES; 20 | import static org.abstractj.kalium.NaCl.sodium; 21 | import static org.abstractj.kalium.crypto.Util.checkLength; 22 | 23 | public class Advanced { 24 | 25 | public byte[] crypto_stream_xsalsa20_xor(byte[] message, byte[] nonce, byte[] key) { 26 | 27 | checkLength(nonce, CRYPTO_STREAM_NONCEBYTES); 28 | checkLength(key, CRYPTO_STREAM_KEYBYTES); 29 | byte[] buffer = new byte[message.length]; 30 | sodium().crypto_stream_xor(buffer, message, message.length, nonce, key); 31 | return buffer; 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/ShortHash.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import static org.abstractj.kalium.NaCl.sodium; 20 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SHORTHASH_SIPHASH24_BYTES; 21 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SHORTHASH_SIPHASH24_KEYBYTES; 22 | import static org.abstractj.kalium.crypto.Util.checkLength; 23 | import static org.abstractj.kalium.crypto.Util.isValid; 24 | 25 | public class ShortHash { 26 | 27 | public byte[] siphash24(byte[] message, byte[] key) { 28 | byte[] buffer = new byte[CRYPTO_SHORTHASH_SIPHASH24_BYTES]; 29 | checkLength(key, CRYPTO_SHORTHASH_SIPHASH24_KEYBYTES); 30 | isValid(sodium().crypto_shorthash_siphash24(buffer, message, message.length, key), "Hashing failed"); 31 | return buffer; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/PublicKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; 20 | import static org.abstractj.kalium.crypto.Util.checkLength; 21 | import static org.abstractj.kalium.encoders.Encoder.HEX; 22 | 23 | public class PublicKey implements Key { 24 | 25 | private final byte[] publicKey; 26 | 27 | public PublicKey(byte[] publicKey) { 28 | this.publicKey = publicKey; 29 | checkLength(publicKey, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES); 30 | } 31 | 32 | public PublicKey(String publicKey) { 33 | this.publicKey = HEX.decode(publicKey); 34 | } 35 | 36 | public byte[] toBytes() { 37 | return publicKey; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return HEX.encode(publicKey); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/PrivateKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES; 20 | import static org.abstractj.kalium.crypto.Util.checkLength; 21 | import static org.abstractj.kalium.encoders.Encoder.HEX; 22 | 23 | public class PrivateKey implements Key { 24 | 25 | private final byte[] secretKey; 26 | 27 | public PrivateKey(byte[] secretKey) { 28 | this.secretKey = secretKey; 29 | checkLength(secretKey, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES); 30 | } 31 | 32 | public PrivateKey(String secretKey) { 33 | this.secretKey = HEX.decode(secretKey); 34 | checkLength(this.secretKey, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES); 35 | } 36 | 37 | @Override 38 | public byte[] toBytes() { 39 | return secretKey; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return HEX.encode(secretKey); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Password.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.crypto; 2 | 3 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OUTBYTES; 4 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRBYTES; 5 | import static org.abstractj.kalium.NaCl.sodium; 6 | import org.abstractj.kalium.encoders.Encoder; 7 | 8 | public class Password { 9 | 10 | public Password() { 11 | } 12 | public byte[] deriveKey(int length, byte[] passwd, byte[] salt, int opslimit, long memlimit) { 13 | byte[] buffer = new byte[length]; 14 | sodium().crypto_pwhash_scryptsalsa208sha256(buffer, buffer.length, passwd, passwd.length, salt, opslimit, memlimit); 15 | return buffer; 16 | } 17 | 18 | public String hash(byte[] passwd, Encoder encoder, byte[] salt, int opslimit, long memlimit) { 19 | byte[] buffer = deriveKey(CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OUTBYTES, passwd, salt, opslimit, memlimit); 20 | return encoder.encode(buffer); 21 | } 22 | 23 | public String hash(int length, byte[] passwd, Encoder encoder, byte[] salt, int opslimit, long memlimit) { 24 | byte[] buffer = deriveKey(length, passwd, salt, opslimit, memlimit); 25 | return encoder.encode(buffer); 26 | } 27 | 28 | public String hash(byte[] passwd, Encoder encoder, int opslimit, long memlimit) { 29 | byte[] buffer = new byte[CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRBYTES]; 30 | sodium().crypto_pwhash_scryptsalsa208sha256_str(buffer, passwd, passwd.length, opslimit, memlimit); 31 | return encoder.encode(buffer); 32 | } 33 | 34 | public boolean verify(byte[] hashed_passwd, byte[] passwd) { 35 | int result = sodium().crypto_pwhash_scryptsalsa208sha256_str_verify(hashed_passwd, passwd, passwd.length); 36 | return result == 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/RandomTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertFalse; 25 | 26 | public class RandomTest { 27 | 28 | @Test 29 | public void testProducesRandomBytes() throws Exception { 30 | final int size = 16; 31 | assertEquals("Invalid random bytes", size, new Random().randomBytes(size).length); 32 | } 33 | 34 | @Test 35 | public void testProducesDefaultRandomBytes() throws Exception { 36 | final int size = 32; 37 | assertEquals("Invalid random bytes", size, new Random().randomBytes().length); 38 | } 39 | 40 | @Test 41 | public void testProducesDifferentRandomBytes() throws Exception { 42 | final int size = 16; 43 | assertFalse("Should produce different random bytes", Arrays.equals(new Random().randomBytes(size), new Random().randomBytes(size))); 44 | } 45 | 46 | @Test 47 | public void testProducesDifferentDefaultRandomBytes() throws Exception { 48 | final int size = 32; 49 | assertFalse("Should produce different random bytes", Arrays.equals(new Random().randomBytes(), new Random().randomBytes(size))); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/SealedBox.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.crypto; 2 | 3 | import org.abstractj.kalium.encoders.Encoder; 4 | 5 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_SEALBYTES; 6 | import static org.abstractj.kalium.NaCl.sodium; 7 | import static org.abstractj.kalium.crypto.Util.isValid; 8 | 9 | public class SealedBox { 10 | 11 | private byte[] publicKey; 12 | private byte[] privateKey; 13 | 14 | public SealedBox(byte[] publicKey) { 15 | this.publicKey = publicKey; 16 | this.privateKey = null; 17 | } 18 | 19 | public SealedBox(String publicKey, Encoder encoder) { 20 | this(encoder.decode(publicKey)); 21 | } 22 | 23 | public SealedBox(byte[] publicKey, byte[] privateKey) { 24 | this.publicKey = publicKey; 25 | this.privateKey = privateKey; 26 | } 27 | 28 | public SealedBox(String publicKey, String privateKey, Encoder encoder) { 29 | this(encoder.decode(publicKey), encoder.decode(privateKey)); 30 | } 31 | 32 | public byte[] encrypt(byte[] message) { 33 | if (publicKey == null) 34 | throw new RuntimeException("Encryption failed. Public key not available."); 35 | byte[] ct = new byte[message.length + CRYPTO_BOX_SEALBYTES]; 36 | isValid(sodium().crypto_box_seal( 37 | ct, message, message.length, publicKey), 38 | "Encryption failed"); 39 | return ct; 40 | } 41 | 42 | public byte[] decrypt(byte[] ciphertext) { 43 | if (privateKey == null) 44 | throw new RuntimeException("Decryption failed. Private key not available."); 45 | 46 | byte[] message = new byte[ciphertext.length - CRYPTO_BOX_SEALBYTES]; 47 | isValid(sodium().crypto_box_seal_open( 48 | message, ciphertext, ciphertext.length, publicKey, privateKey), 49 | "Decryption failed. Ciphertext failed verification"); 50 | return message; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/AeadTest.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.crypto; 2 | 3 | import org.abstractj.kalium.NaCl; 4 | import org.junit.Test; 5 | 6 | import static org.abstractj.kalium.NaCl.sodium; 7 | import static org.abstractj.kalium.encoders.Encoder.HEX; 8 | import static org.abstractj.kalium.fixture.TestVectors.*; 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | public class AeadTest { 12 | @Test 13 | public void testEncrypt() throws Exception { 14 | byte[] key = HEX.decode(AEAD_KEY); 15 | byte[] publicNonce = HEX.decode(AEAD_NONCE); 16 | byte[] message = HEX.decode(AEAD_MESSAGE); 17 | byte[] ad = HEX.decode(AEAD_AD); 18 | 19 | Aead aead = new Aead(key); 20 | byte[] ct = aead.encrypt(publicNonce, message, ad); 21 | assertArrayEquals(HEX.decode(AEAD_CT), ct); 22 | } 23 | 24 | @Test 25 | public void testDecrypt() throws Exception { 26 | byte[] key = HEX.decode(AEAD_KEY); 27 | byte[] publicNonce = HEX.decode(AEAD_NONCE); 28 | byte[] ct = HEX.decode(AEAD_CT); 29 | byte[] ad = HEX.decode(AEAD_AD); 30 | 31 | Aead aead = new Aead(key); 32 | byte[] message = aead.decrypt(publicNonce, ct, ad); 33 | assertArrayEquals(HEX.decode(AEAD_MESSAGE), message); 34 | } 35 | 36 | @Test 37 | public void testAES256GCM() throws Exception { 38 | sodium().sodium_init(); 39 | if (sodium().crypto_aead_aes256gcm_is_available() != 1) { 40 | System.out.println("AES256-GCM is not supported"); 41 | return; 42 | } 43 | 44 | byte[] key = HEX.decode(AEAD_KEY); 45 | byte[] publicNonce = new Random().randomBytes(NaCl.Sodium.CRYPTO_AEAD_AES256GCM_NPUBBYTES); 46 | byte[] message = HEX.decode(AEAD_MESSAGE); 47 | byte[] ad = HEX.decode(AEAD_AD); 48 | 49 | Aead aead = new Aead(key).useAesGcm(); 50 | byte[] ct = aead.encrypt(publicNonce, message, ad); 51 | byte[] msg2 = aead.decrypt(publicNonce, ct, ad); 52 | assertArrayEquals(message, msg2); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Point.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.abstractj.kalium.encoders.Encoder; 20 | 21 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SCALARMULT_CURVE25519_SCALARBYTES; 22 | import static org.abstractj.kalium.NaCl.sodium; 23 | import static org.abstractj.kalium.crypto.Util.zeros; 24 | import static org.abstractj.kalium.encoders.Encoder.HEX; 25 | 26 | public class Point { 27 | 28 | private static final String STANDARD_GROUP_ELEMENT = "0900000000000000000000000000000000000000000000000000000000000000"; 29 | 30 | private final byte[] point; 31 | 32 | public Point() { 33 | this.point = HEX.decode(STANDARD_GROUP_ELEMENT); 34 | } 35 | 36 | public Point(byte[] point) { 37 | this.point = point; 38 | } 39 | 40 | public Point(String point, Encoder encoder) { 41 | this(encoder.decode(point)); 42 | } 43 | 44 | public Point mult(byte[] n) { 45 | byte[] result = zeros(CRYPTO_SCALARMULT_CURVE25519_SCALARBYTES); 46 | sodium().crypto_scalarmult_curve25519(result, n, point); 47 | return new Point(result); 48 | } 49 | 50 | public Point mult(String n, Encoder encoder) { 51 | return mult(encoder.decode(n)); 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return HEX.encode(point); 57 | } 58 | 59 | public byte[] toBytes() { 60 | return point; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Util.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import java.util.Arrays; 20 | 21 | public class Util { 22 | 23 | private static final int DEFAULT_SIZE = 32; 24 | 25 | public static byte[] prependZeros(int n, byte[] message) { 26 | byte[] result = new byte[n + message.length]; 27 | System.arraycopy(message, 0, result, n, message.length); 28 | return result; 29 | } 30 | 31 | public static byte[] removeZeros(int n, byte[] message) { 32 | return Arrays.copyOfRange(message, n, message.length); 33 | } 34 | 35 | public static void checkLength(byte[] data, int size) { 36 | if (data == null || data.length != size) 37 | throw new RuntimeException("Invalid size"); 38 | } 39 | 40 | public static byte[] zeros(int n) { 41 | return new byte[n]; 42 | } 43 | 44 | public static boolean isValid(int status, String message) { 45 | if (status != 0) 46 | throw new RuntimeException(message); 47 | return true; 48 | } 49 | 50 | public static byte[] slice(byte[] buffer, int start, int end) { 51 | return Arrays.copyOfRange(buffer, start, end); 52 | } 53 | 54 | public static byte[] merge(byte[] signature, byte[] message) { 55 | byte[] result = new byte[signature.length + message.length]; 56 | System.arraycopy(signature, 0, result, 0, signature.length); 57 | System.arraycopy(message, 0, result, signature.length, message.length); 58 | return result; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/VerifyKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import org.abstractj.kalium.encoders.Encoder; 20 | 21 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; 22 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SIGN_ED25519_BYTES; 23 | import static org.abstractj.kalium.NaCl.sodium; 24 | import static org.abstractj.kalium.crypto.Util.checkLength; 25 | import static org.abstractj.kalium.crypto.Util.isValid; 26 | import static org.abstractj.kalium.encoders.Encoder.HEX; 27 | 28 | public class VerifyKey { 29 | 30 | private byte[] key; 31 | 32 | public VerifyKey(byte[] key) { 33 | checkLength(key, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES); 34 | this.key = key; 35 | } 36 | 37 | public VerifyKey(String key, Encoder encoder) { 38 | this(encoder.decode(key)); 39 | } 40 | 41 | public boolean verify(byte[] message, byte[] signature) { 42 | checkLength(signature, CRYPTO_SIGN_ED25519_BYTES); 43 | return isValid(sodium().crypto_sign_ed25519_verify_detached(signature, message, message.length, key), "signature was forged or corrupted"); 44 | } 45 | 46 | public boolean verify(String message, String signature, Encoder encoder) { 47 | return verify(encoder.decode(message), encoder.decode(signature)); 48 | } 49 | 50 | public byte[] toBytes() { 51 | return key; 52 | } 53 | 54 | @Override 55 | public String toString(){ 56 | return HEX.encode(key); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/encoders/RawTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.encoders; 18 | 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | 22 | import java.util.Arrays; 23 | 24 | import static org.junit.Assert.assertTrue; 25 | import static org.junit.Assert.assertEquals; 26 | import static org.junit.Assert.assertNull; 27 | import static org.junit.Assert.fail; 28 | 29 | public class RawTest { 30 | 31 | private Encoder encoder; 32 | 33 | @Before 34 | public void setUp() { 35 | encoder = new Raw(); 36 | } 37 | 38 | @Test 39 | public void testEncode() throws Exception { 40 | String value = "hello"; 41 | assertEquals(value, encoder.encode(value.getBytes())); 42 | } 43 | 44 | @Test 45 | public void testEncodeNullString() throws Exception { 46 | byte[] value = null; 47 | try { 48 | assertNull(encoder.encode(value)); 49 | } catch (Exception e) { 50 | fail("Should not raise any exception"); 51 | } 52 | } 53 | 54 | @Test 55 | public void testDecode() throws Exception { 56 | String value = "hello"; 57 | assertTrue(Arrays.equals(encoder.decode(value), value.getBytes())); 58 | } 59 | 60 | @Test 61 | public void testDecodeNullString() throws Exception { 62 | String value = null; 63 | try { 64 | assertNull(encoder.decode(value)); 65 | } catch (Exception e) { 66 | e.printStackTrace(); 67 | fail("Should not raise any exception"); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/ShortHashTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.abstractj.kalium.encoders.Encoder.HEX; 22 | import static org.abstractj.kalium.fixture.TestVectors.SIPHASH24_KEY; 23 | import static org.abstractj.kalium.fixture.TestVectors.SIPHASH24_MESSAGE; 24 | import static org.abstractj.kalium.fixture.TestVectors.SIPHASH24_DIGEST; 25 | import static org.abstractj.kalium.fixture.TestVectors.SIPHASH24_DIGEST_EMPTY_STRING; 26 | 27 | import static org.junit.Assert.assertEquals; 28 | 29 | public class ShortHashTest { 30 | 31 | private final ShortHash hash = new ShortHash(); 32 | 33 | @Test 34 | public void testSiphash24() throws Exception { 35 | byte[] message = HEX.decode(SIPHASH24_MESSAGE); 36 | byte[] key = HEX.decode(SIPHASH24_KEY); 37 | String result = HEX.encode(hash.siphash24(message, key)); 38 | assertEquals("Hash is invalid", SIPHASH24_DIGEST, result); 39 | } 40 | 41 | @Test 42 | public void testSiphash24EmptyString() throws Exception { 43 | byte[] key = HEX.decode(SIPHASH24_KEY); 44 | String result = HEX.encode(hash.siphash24(new byte[0], key)); 45 | assertEquals("Hash is invalid", SIPHASH24_DIGEST_EMPTY_STRING, result); 46 | } 47 | 48 | @Test(expected = RuntimeException.class) 49 | public void testSiphash24InvalidKey() throws Exception { 50 | byte[] message = HEX.decode(SIPHASH24_MESSAGE); 51 | byte[] invalidKey = new byte[1]; 52 | hash.siphash24(message, invalidKey); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/KeyPair.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import org.abstractj.kalium.crypto.Point; 20 | import org.abstractj.kalium.encoders.Encoder; 21 | 22 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; 23 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES; 24 | import static org.abstractj.kalium.NaCl.sodium; 25 | import static org.abstractj.kalium.crypto.Util.checkLength; 26 | import static org.abstractj.kalium.crypto.Util.zeros; 27 | 28 | public class KeyPair { 29 | 30 | private final byte[] publicKey; 31 | private final byte[] secretKey; 32 | 33 | public KeyPair() { 34 | this.secretKey = zeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES); 35 | this.publicKey = zeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES); 36 | sodium().crypto_box_curve25519xsalsa20poly1305_keypair(publicKey, secretKey); 37 | } 38 | 39 | public KeyPair(byte[] secretKey) { 40 | this.secretKey = secretKey; 41 | checkLength(this.secretKey, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES); 42 | Point point = new Point(); 43 | this.publicKey = point.mult(secretKey).toBytes(); 44 | } 45 | 46 | public KeyPair(String secretKey, Encoder encoder) { 47 | this(encoder.decode(secretKey)); 48 | } 49 | 50 | public PublicKey getPublicKey() { 51 | return new PublicKey(publicKey); 52 | } 53 | 54 | public PrivateKey getPrivateKey() { 55 | return new PrivateKey(secretKey); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/PointTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | 23 | import static org.abstractj.kalium.encoders.Encoder.HEX; 24 | import static org.abstractj.kalium.fixture.TestVectors.ALICE_MULT_BOB; 25 | import static org.abstractj.kalium.fixture.TestVectors.ALICE_PRIVATE_KEY; 26 | import static org.abstractj.kalium.fixture.TestVectors.ALICE_PUBLIC_KEY; 27 | import static org.abstractj.kalium.fixture.TestVectors.BOB_PUBLIC_KEY; 28 | import static org.junit.Assert.assertEquals; 29 | import static org.junit.Assert.assertTrue; 30 | 31 | public class PointTest { 32 | 33 | @Test 34 | public void testMultipleIntegersWithBasePoint() throws Exception { 35 | Point point = new Point(); 36 | String mult = point.mult(ALICE_PRIVATE_KEY, HEX).toString(); 37 | assertEquals("Should return a serialized point", ALICE_PUBLIC_KEY, mult); 38 | } 39 | 40 | @Test 41 | public void testMultipleIntegersWithArbitraryPoints() throws Exception { 42 | Point point = new Point(BOB_PUBLIC_KEY, HEX); 43 | String mult = point.mult(ALICE_PRIVATE_KEY, HEX).toString(); 44 | assertEquals("Should return a valid serialized point", ALICE_MULT_BOB, mult); 45 | } 46 | 47 | @Test 48 | public void testSerializeToBytes() throws Exception { 49 | Point point = new Point(BOB_PUBLIC_KEY, HEX); 50 | assertTrue("Should serialize to bytes", Arrays.equals(HEX.decode(BOB_PUBLIC_KEY), point.toBytes())); 51 | } 52 | 53 | @Test 54 | public void testSerializeToHex() throws Exception { 55 | Point point = new Point(BOB_PUBLIC_KEY, HEX); 56 | assertEquals("Should serialize to hex", BOB_PUBLIC_KEY, point.toString()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/AuthenticationKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 Cisco Systems, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import org.abstractj.kalium.encoders.Encoder; 20 | 21 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_AUTH_HMACSHA512256_BYTES; 22 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_AUTH_HMACSHA512256_KEYBYTES; 23 | import static org.abstractj.kalium.NaCl.sodium; 24 | import static org.abstractj.kalium.crypto.Util.checkLength; 25 | import static org.abstractj.kalium.crypto.Util.isValid; 26 | import static org.abstractj.kalium.encoders.Encoder.HEX; 27 | 28 | 29 | public class AuthenticationKey implements Key { 30 | 31 | private byte[] key; 32 | 33 | public AuthenticationKey(byte[] key) { 34 | this.key = key; 35 | checkLength(key, CRYPTO_AUTH_HMACSHA512256_KEYBYTES); 36 | } 37 | 38 | public AuthenticationKey(String key, Encoder encoder) { 39 | this(encoder.decode(key)); 40 | } 41 | 42 | public byte[] sign(byte[] message) { 43 | byte[] mac = new byte[CRYPTO_AUTH_HMACSHA512256_BYTES]; 44 | sodium().crypto_auth_hmacsha512256(mac, message, message.length, key); 45 | return mac; 46 | } 47 | 48 | public String sign(String message, Encoder encoder) { 49 | byte[] signature = sign(encoder.decode(message)); 50 | return encoder.encode(signature); 51 | } 52 | 53 | public boolean verify(byte[] message, byte[] signature) { 54 | checkLength(signature, CRYPTO_AUTH_HMACSHA512256_BYTES); 55 | return isValid(sodium().crypto_auth_hmacsha512256_verify(signature, message, message.length, key), "signature was forged or corrupted"); 56 | } 57 | 58 | public boolean verify(String message, String signature, Encoder encoder) { 59 | return verify(encoder.decode(message), encoder.decode(signature)); 60 | } 61 | 62 | @Override 63 | public byte[] toBytes() { 64 | return key; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return HEX.encode(key); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/SecretBox.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.abstractj.kalium.encoders.Encoder; 20 | 21 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES; 22 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SECRETBOX_XSALSA20POLY1305_NONCEBYTES; 23 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES; 24 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES; 25 | import static org.abstractj.kalium.NaCl.sodium; 26 | import static org.abstractj.kalium.crypto.Util.checkLength; 27 | import static org.abstractj.kalium.crypto.Util.isValid; 28 | import static org.abstractj.kalium.crypto.Util.removeZeros; 29 | 30 | public class SecretBox { 31 | 32 | private byte[] key; 33 | 34 | public SecretBox(byte[] key) { 35 | this.key = key; 36 | checkLength(key, CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES); 37 | } 38 | 39 | public SecretBox(String key, Encoder encoder) { 40 | this(encoder.decode(key)); 41 | } 42 | 43 | public byte[] encrypt(byte[] nonce, byte[] message) { 44 | checkLength(nonce, CRYPTO_SECRETBOX_XSALSA20POLY1305_NONCEBYTES); 45 | byte[] msg = Util.prependZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES, message); 46 | byte[] ct = Util.zeros(msg.length); 47 | isValid(sodium().crypto_secretbox_xsalsa20poly1305(ct, msg, msg.length, 48 | nonce, key), "Encryption failed"); 49 | return removeZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES, ct); 50 | } 51 | 52 | public byte[] decrypt(byte[] nonce, byte[] ciphertext) { 53 | checkLength(nonce, CRYPTO_SECRETBOX_XSALSA20POLY1305_NONCEBYTES); 54 | byte[] ct = Util.prependZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES, ciphertext); 55 | byte[] message = Util.zeros(ct.length); 56 | isValid(sodium().crypto_secretbox_xsalsa20poly1305_open(message, ct, 57 | ct.length, nonce, key), "Decryption failed. Ciphertext failed verification"); 58 | return removeZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES, message); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Hash.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.abstractj.kalium.encoders.Encoder; 20 | 21 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_GENERICHASH_BLAKE2B_BYTES; 22 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_HASH_SHA256_BYTES; 23 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_HASH_SHA512_BYTES; 24 | import static org.abstractj.kalium.NaCl.sodium; 25 | 26 | public class Hash { 27 | 28 | public byte[] sha256(byte[] message) { 29 | byte[] buffer = new byte[CRYPTO_HASH_SHA256_BYTES]; 30 | sodium().crypto_hash_sha256(buffer, message, message.length); 31 | return buffer; 32 | } 33 | 34 | public byte[] sha512(byte[] message) { 35 | byte[] buffer = new byte[CRYPTO_HASH_SHA512_BYTES]; 36 | sodium().crypto_hash_sha512(buffer, message, message.length); 37 | return buffer; 38 | } 39 | 40 | public String sha256(String message, Encoder encoder) { 41 | byte[] hash = sha256(message.getBytes()); 42 | return encoder.encode(hash); 43 | } 44 | 45 | public String sha512(String message, Encoder encoder) { 46 | byte[] hash = sha512(message.getBytes()); 47 | return encoder.encode(hash); 48 | } 49 | 50 | 51 | public byte[] blake2(byte[] message) throws UnsupportedOperationException { 52 | byte[] buffer = new byte[CRYPTO_GENERICHASH_BLAKE2B_BYTES]; 53 | sodium().crypto_generichash_blake2b(buffer, CRYPTO_GENERICHASH_BLAKE2B_BYTES, message, message.length, null, 0); 54 | return buffer; 55 | } 56 | 57 | public String blake2(String message, Encoder encoder) throws UnsupportedOperationException { 58 | byte[] hash = blake2(message.getBytes()); 59 | return encoder.encode(hash); 60 | } 61 | 62 | public byte[] blake2(byte[] message, byte[] key, byte[] salt, byte[] personal) throws UnsupportedOperationException { 63 | byte[] buffer = new byte[CRYPTO_GENERICHASH_BLAKE2B_BYTES]; 64 | sodium().crypto_generichash_blake2b_salt_personal(buffer, CRYPTO_GENERICHASH_BLAKE2B_BYTES, 65 | message, message.length, 66 | key, key.length, 67 | salt, personal); 68 | return buffer; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/SealedBoxTest.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.crypto; 2 | 3 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; 4 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES; 5 | import static org.abstractj.kalium.NaCl.sodium; 6 | import static org.junit.Assert.assertArrayEquals; 7 | 8 | import java.security.SecureRandom; 9 | import org.abstractj.kalium.keys.KeyPair; 10 | import org.junit.Test; 11 | 12 | public class SealedBoxTest { 13 | 14 | @Test 15 | public void testEncryptDecrypt() throws Exception { 16 | SecureRandom r = new SecureRandom(); 17 | KeyPair keyPair = new KeyPair(new byte[CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES]); 18 | byte[] sk = keyPair.getPrivateKey().toBytes(); 19 | byte[] pk = keyPair.getPublicKey().toBytes(); 20 | byte[] m = new byte[r.nextInt(1000)]; 21 | 22 | r.nextBytes(m); 23 | SealedBox sb = new SealedBox(pk); 24 | byte[] c = sb.encrypt(m); 25 | 26 | SealedBox sb2 = new SealedBox(pk, sk); 27 | byte[] m2 = sb2.decrypt(c); 28 | assertArrayEquals(m, m2); 29 | } 30 | 31 | @Test 32 | public void testEncryptDecryptMultPublicKeys() throws Exception { 33 | SecureRandom r = new SecureRandom(); 34 | KeyPair keyPair = new KeyPair(new byte[CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES]); 35 | byte[] sk = keyPair.getPrivateKey().toBytes(); 36 | byte[] pk1 = keyPair.getPublicKey().toBytes(); 37 | byte[] pk2 = new byte[pk1.length]; 38 | 39 | sodium().crypto_scalarmult_base(pk2, sk); 40 | 41 | byte[] m = new byte[r.nextInt(1000)]; 42 | r.nextBytes(m); 43 | 44 | SealedBox sb1 = new SealedBox(pk1); 45 | byte[] c1 = sb1.encrypt(m); 46 | 47 | SealedBox sb2 = new SealedBox(pk2); 48 | byte[] c2 = sb2.encrypt(m); 49 | 50 | SealedBox sb3 = new SealedBox(pk1, sk); 51 | byte[] m2 = sb3.decrypt(c1); 52 | byte[] m3 = sb3.decrypt(c2); 53 | assertArrayEquals(m, m2); 54 | assertArrayEquals(m2, m3); 55 | } 56 | 57 | @Test(expected = RuntimeException.class) 58 | public void testDecryptFailsFlippedKeys() throws Exception { 59 | SecureRandom r = new SecureRandom(); 60 | byte[] pk = new byte[CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES]; 61 | byte[] sk = new byte[CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES]; 62 | byte[] m = new byte[r.nextInt(1000)]; 63 | 64 | sodium().crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk); 65 | r.nextBytes(m); 66 | 67 | SealedBox sb = new SealedBox(pk); 68 | byte[] c = sb.encrypt(m); 69 | SealedBox sb2 = new SealedBox(sk, pk); 70 | sb2.decrypt(c); 71 | } 72 | 73 | @Test(expected = RuntimeException.class) 74 | public void testDecryptFailsWithNull() throws Exception { 75 | SecureRandom r = new SecureRandom(); 76 | byte[] pk = null; 77 | byte[] sk = null; 78 | byte[] m = new byte[r.nextInt(1000)]; 79 | 80 | SealedBox sb = new SealedBox(pk); 81 | byte[] c = sb.encrypt(m); 82 | SealedBox sb2 = new SealedBox(sk, pk); 83 | sb2.decrypt(c); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/keys/SigningKey.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import jnr.ffi.byref.LongLongByReference; 20 | import org.abstractj.kalium.crypto.Random; 21 | import org.abstractj.kalium.crypto.Util; 22 | import org.abstractj.kalium.encoders.Encoder; 23 | 24 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; 25 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES; 26 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_SIGN_ED25519_BYTES; 27 | import static org.abstractj.kalium.NaCl.sodium; 28 | import static org.abstractj.kalium.crypto.Util.checkLength; 29 | import static org.abstractj.kalium.crypto.Util.isValid; 30 | import static org.abstractj.kalium.crypto.Util.slice; 31 | import static org.abstractj.kalium.crypto.Util.zeros; 32 | import static org.abstractj.kalium.encoders.Encoder.HEX; 33 | 34 | public class SigningKey { 35 | 36 | private final byte[] seed; 37 | private final byte[] secretKey; 38 | private final VerifyKey verifyKey; 39 | 40 | public SigningKey(byte[] seed) { 41 | checkLength(seed, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES); 42 | this.seed = seed; 43 | this.secretKey = zeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES * 2); 44 | byte[] publicKey = zeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES); 45 | isValid(sodium().crypto_sign_ed25519_seed_keypair(publicKey, secretKey, seed), 46 | "Failed to generate a key pair"); 47 | 48 | this.verifyKey = new VerifyKey(publicKey); 49 | } 50 | 51 | public SigningKey() { 52 | this(new Random().randomBytes(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES)); 53 | } 54 | 55 | public SigningKey(String seed, Encoder encoder) { 56 | this(encoder.decode(seed)); 57 | } 58 | 59 | public VerifyKey getVerifyKey() { 60 | return this.verifyKey; 61 | } 62 | 63 | public byte[] sign(byte[] message) { 64 | byte[] signature = new byte[CRYPTO_SIGN_ED25519_BYTES]; 65 | LongLongByReference bufferLen = new LongLongByReference(0); 66 | sodium().crypto_sign_ed25519_detached(signature, bufferLen, message, message.length, secretKey); 67 | return signature; 68 | } 69 | 70 | public String sign(String message, Encoder encoder) { 71 | byte[] signature = sign(encoder.decode(message)); 72 | return encoder.encode(signature); 73 | } 74 | 75 | public byte[] toBytes() { 76 | return seed; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return HEX.encode(seed); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/SecretBoxTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | 23 | import static org.abstractj.kalium.encoders.Encoder.HEX; 24 | import static org.abstractj.kalium.fixture.TestVectors.BOX_CIPHERTEXT; 25 | import static org.abstractj.kalium.fixture.TestVectors.BOX_MESSAGE; 26 | import static org.abstractj.kalium.fixture.TestVectors.BOX_NONCE; 27 | import static org.abstractj.kalium.fixture.TestVectors.SECRET_KEY; 28 | import static org.junit.Assert.assertTrue; 29 | import static org.junit.Assert.fail; 30 | 31 | public class SecretBoxTest { 32 | 33 | @Test 34 | public void testAcceptStrings() throws Exception { 35 | try { 36 | new SecretBox(SECRET_KEY, HEX); 37 | } catch (Exception e) { 38 | fail("SecretBox should accept strings"); 39 | } 40 | } 41 | 42 | @Test(expected = RuntimeException.class) 43 | public void testNullKey() throws Exception { 44 | byte[] key = null; 45 | new SecretBox(key); 46 | fail("Should raise an exception"); 47 | } 48 | 49 | @Test(expected = RuntimeException.class) 50 | public void testShortKey() throws Exception { 51 | String key = "hello"; 52 | new SecretBox(key.getBytes()); 53 | fail("Should raise an exception"); 54 | } 55 | 56 | @Test 57 | public void testEncrypt() throws Exception { 58 | SecretBox box = new SecretBox(SECRET_KEY, HEX); 59 | 60 | byte[] nonce = HEX.decode(BOX_NONCE); 61 | byte[] message = HEX.decode(BOX_MESSAGE); 62 | byte[] ciphertext = HEX.decode(BOX_CIPHERTEXT); 63 | 64 | byte[] result = box.encrypt(nonce, message); 65 | assertTrue("failed to generate ciphertext", Arrays.equals(result, ciphertext)); 66 | } 67 | 68 | @Test 69 | public void testDecrypt() throws Exception { 70 | 71 | SecretBox box = new SecretBox(SECRET_KEY, HEX); 72 | 73 | byte[] nonce = HEX.decode(BOX_NONCE); 74 | byte[] expectedMessage = HEX.decode(BOX_MESSAGE); 75 | byte[] ciphertext = box.encrypt(nonce, expectedMessage); 76 | 77 | byte[] message = box.decrypt(nonce, ciphertext); 78 | 79 | assertTrue("failed to decrypt ciphertext", Arrays.equals(message, expectedMessage)); 80 | } 81 | 82 | @Test(expected = RuntimeException.class) 83 | public void testDecryptCorruptedCipherText() throws Exception { 84 | SecretBox box = new SecretBox(SECRET_KEY, HEX); 85 | byte[] nonce = HEX.decode(BOX_NONCE); 86 | byte[] message = HEX.decode(BOX_MESSAGE); 87 | byte[] ciphertext = box.encrypt(nonce, message); 88 | ciphertext[23] = ' '; 89 | 90 | box.decrypt(nonce, ciphertext); 91 | fail("Should raise an exception"); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/keys/VerifyKeyTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | 23 | import static org.junit.Assert.assertTrue; 24 | import static org.junit.Assert.assertEquals; 25 | import static org.abstractj.kalium.encoders.Encoder.HEX; 26 | import static org.abstractj.kalium.fixture.TestVectors.SIGN_MESSAGE; 27 | import static org.abstractj.kalium.fixture.TestVectors.SIGN_PRIVATE; 28 | import static org.abstractj.kalium.fixture.TestVectors.SIGN_PUBLIC; 29 | import static org.abstractj.kalium.fixture.TestVectors.SIGN_SIGNATURE; 30 | import static org.junit.Assert.fail; 31 | 32 | public class VerifyKeyTest { 33 | 34 | @Test 35 | public void testVerifyCorrectRawSignature() throws Exception { 36 | byte[] rawSignature = HEX.decode(SIGN_SIGNATURE); 37 | byte[] rawMessage = HEX.decode(SIGN_MESSAGE); 38 | byte[] rawPublicKey = HEX.decode(SIGN_PUBLIC); 39 | VerifyKey verifyKey = new VerifyKey(rawPublicKey); 40 | assertTrue(verifyKey.verify(rawMessage, rawSignature)); 41 | } 42 | 43 | @Test 44 | public void testVerifyCorrectHexSignature() throws Exception { 45 | byte[] rawPublicKey = HEX.decode(SIGN_PUBLIC); 46 | VerifyKey verifyKey = new VerifyKey(rawPublicKey); 47 | verifyKey.verify(SIGN_MESSAGE, SIGN_SIGNATURE, HEX); 48 | assertTrue(verifyKey.verify(SIGN_MESSAGE, SIGN_SIGNATURE, HEX)); 49 | } 50 | 51 | @Test 52 | public void testDetectBadSignature() throws Exception { 53 | try { 54 | String badSignature = SIGN_SIGNATURE.concat("0000"); 55 | VerifyKey verifyKey = new VerifyKey(SIGN_PUBLIC, HEX); 56 | verifyKey.verify(SIGN_MESSAGE, badSignature, HEX); 57 | fail("Should an exception on bad signatures"); 58 | } catch (Exception e) { 59 | assertTrue(true); 60 | } 61 | } 62 | 63 | @Test 64 | public void testSerializeToBytes() throws Exception { 65 | byte[] rawPublic = HEX.decode(SIGN_PUBLIC); 66 | VerifyKey verifyKey = new VerifyKey(SIGN_PUBLIC, HEX); 67 | verifyKey.verify(SIGN_MESSAGE, SIGN_SIGNATURE, HEX); 68 | assertTrue(Arrays.equals(verifyKey.toBytes(), rawPublic)); 69 | } 70 | 71 | @Test 72 | public void testSerializeToString() throws Exception { 73 | SigningKey key = new SigningKey(SIGN_PRIVATE, HEX); 74 | VerifyKey verifyKey = new VerifyKey(SIGN_PUBLIC, HEX); 75 | verifyKey.verify(SIGN_MESSAGE, SIGN_SIGNATURE, HEX); 76 | assertEquals(verifyKey.toString(), SIGN_PUBLIC); 77 | } 78 | 79 | @Test 80 | public void testInitializeFromHex() throws Exception { 81 | VerifyKey verifyKey = new VerifyKey(SIGN_PUBLIC, HEX); 82 | assertTrue(verifyKey.verify(SIGN_MESSAGE, SIGN_SIGNATURE, HEX)); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/AdvancedTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.junit.Assert.assertEquals; 22 | import static org.junit.Assert.assertNotEquals; 23 | 24 | public class AdvancedTest { 25 | 26 | @Test 27 | public void testXsalsa20HappyFlow() { 28 | Random random = new Random(); 29 | Advanced advanced = new Advanced(); 30 | byte[] nonce = random.randomBytes(24); 31 | byte[] key = random.randomBytes(32); 32 | String pwd = "This is a test message :-)..."; 33 | byte[] plaintext = pwd.getBytes(); 34 | byte[] ciphertext = advanced.crypto_stream_xsalsa20_xor(plaintext, nonce, key); // encrypt 35 | plaintext = advanced.crypto_stream_xsalsa20_xor(ciphertext, nonce, key); // decrypt 36 | assertEquals(pwd, new String(plaintext)); 37 | } 38 | 39 | @Test 40 | public void testXsalsa20IncorrectNonce() { 41 | Random random = new Random(); 42 | Advanced advanced = new Advanced(); 43 | byte[] nonce = random.randomBytes(24); 44 | byte[] incorrectNonce = random.randomBytes(24); 45 | byte[] key = random.randomBytes(32); 46 | String pwd = "This is a test message :-)..."; 47 | byte[] plaintext = pwd.getBytes(); 48 | byte[] ciphertext = advanced.crypto_stream_xsalsa20_xor(plaintext, nonce, key); // encrypt 49 | plaintext = advanced.crypto_stream_xsalsa20_xor(ciphertext, incorrectNonce, key); // decrypt 50 | assertNotEquals(pwd, new String(plaintext)); 51 | } 52 | 53 | @Test 54 | public void testXsalsa20IncorrectKey() { 55 | Random random = new Random(); 56 | Advanced advanced = new Advanced(); 57 | byte[] nonce = random.randomBytes(24); 58 | byte[] key = random.randomBytes(32); 59 | byte[] incorrectKey = random.randomBytes(32); 60 | String pwd = "This is a test message :-)..."; 61 | byte[] plaintext = pwd.getBytes(); 62 | byte[] ciphertext = advanced.crypto_stream_xsalsa20_xor(plaintext, nonce, key); // encrypt 63 | plaintext = advanced.crypto_stream_xsalsa20_xor(ciphertext, nonce, incorrectKey); // decrypt 64 | assertNotEquals(pwd, new String(plaintext)); 65 | } 66 | 67 | @Test 68 | public void testXsalsa20IncorrectKeyAndIncorrectNonce() { 69 | Random random = new Random(); 70 | Advanced advanced = new Advanced(); 71 | byte[] nonce = random.randomBytes(24); 72 | byte[] incorrectNonce = random.randomBytes(24); 73 | byte[] key = random.randomBytes(32); 74 | byte[] incorrectKey = random.randomBytes(32); 75 | String pwd = "This is a test message :-)..."; 76 | byte[] plaintext = pwd.getBytes(); 77 | byte[] ciphertext = advanced.crypto_stream_xsalsa20_xor(plaintext, nonce, key); // encrypt 78 | plaintext = advanced.crypto_stream_xsalsa20_xor(ciphertext, incorrectNonce, incorrectKey); // decrypt 79 | assertNotEquals(pwd, new String(plaintext)); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](https://img.shields.io/:license-Apache2-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0) 2 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.abstractj.kalium/kalium/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.abstractj.kalium/kalium) 3 | [![Build Status](https://travis-ci.org/abstractj/kalium.png?branch=master)](https://travis-ci.org/abstractj/kalium) 4 | [![Build status](https://ci.appveyor.com/api/projects/status/github/abstractj/kalium?branch=master&svg=true)](https://ci.appveyor.com/project/abstractj/kalium/branch/master) 5 | [![Say Thanks](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/abstractj) 6 | 7 | # kalium - Java binding to the Networking and Cryptography (NaCl) library 8 | 9 | A Java binding to [Networking and Cryptography](http://nacl.cr.yp.to/) library by [Daniel J. Bernstein](http://cr.yp.to/djb.html). All the hard work of making a portable NaCl API version was done by [Frank Denis](https://github.com/jedisct1) on [libsodium](https://github.com/jedisct1/libsodium) and kalium was totally inspired by [Tony Arcieri's](https://github.com/tarcieri) work with [RbNaCl](https://github.com/cryptosphere/rbnacl). 10 | 11 | ## Requirements 12 | 13 | * JDK 6 or [higher](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 14 | * [Apache Maven](http://maven.apache.org/guides/getting-started/) 15 | 16 | ## Installation 17 | 18 | ### libsodium 19 | 20 | kalium is implemented using [jnr-ffi](https://github.com/jnr/jnr-ffi) to bind the shared libraries from [libsodium](https://github.com/jedisct1/libsodium). For a more detailed explanation, please refer to [RbNaCl's documentation](https://github.com/cryptosphere/rbnacl/blob/master/README.md). 21 | 22 | #### OSX 23 | OS X users can get libsodium via [homebrew](http://mxcl.github.com/homebrew/) with: 24 | 25 | brew install libsodium 26 | 27 | #### Windows 28 | Windows users will need to provide the pre-build binaries from `libsodium`. 29 | 30 | - Download `libsodium` from https://download.libsodium.org/libsodium/releases/ 31 | - Choose the version of `libsodium` you wish to use 32 | - The archives follow the following pattern: libsodium-{version}-msvc.zip 33 | - From the archive find the artifacts compiled for your architecture and then the MSVC tool set of your choice 34 | - For example: `v141 // these were compiled against the MSVC v141 (i.e. Visual Studio 2017)` 35 | - Extract from the archive the `dll` library files into **one** of the following locations: 36 | - into the `lib` at the root of the working directory directory of your project. 37 | - into a location that is included in your `PATH` environment variable. 38 | 39 | For example, on Windows 10 machine with a x64 architecture: 40 | ``` 41 | {archive root} 42 | └───x64 43 | ... 44 | └───Release 45 | ... 46 | └───v141 47 | ... 48 | └───dynamic <- copy the library files from this locaiton. 49 | ``` 50 | 51 | ### kalium installation 52 | 53 | Add as a [Maven dependency](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.abstractj.kalium%22%20AND%20a%3A%22kalium%22) to your project. 54 | 55 | ### FAQ 56 | 57 | #### Is Android supported? 58 | No. 59 | 60 | #### Would be nice to have some documentation. Do you have some? 61 | 62 | Look at the libsodium docs, they are self explanatory. Or, contribute with docs. 63 | 64 | #### I'm experiencing some issues on Windows. Do you have any idea? 65 | 66 | I'm sorry but I'm completely clueless about Windows environment, but if you have any suggestions or PR changes. They will be more than welcome. 67 | 68 | ### Notes 69 | 70 | Kalium is the effort of a **really** small group of people, feedback, bug reports and patches are always welcome. 71 | 72 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Aead.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.crypto; 2 | 3 | import org.abstractj.kalium.encoders.Encoder; 4 | 5 | import static org.abstractj.kalium.NaCl.Sodium.*; 6 | import static org.abstractj.kalium.NaCl.sodium; 7 | import static org.abstractj.kalium.crypto.Util.*; 8 | 9 | public class Aead { 10 | 11 | private byte[] key; 12 | 13 | private boolean aesGcm = false; 14 | 15 | public Aead(byte[] key) { 16 | this.key = key; 17 | // both CHACHAPOLY and AESGCM use 32 byte keys 18 | checkLength(key, CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES); 19 | sodium().sodium_init(); // needs to be called here for aes256gcm_is_available() to work 20 | 21 | } 22 | 23 | public Aead(String key, Encoder encoder) { 24 | this(encoder.decode(key)); 25 | } 26 | 27 | public Aead useAesGcm() { 28 | if (sodium().crypto_aead_aes256gcm_is_available() != 1) { 29 | throw new RuntimeException("AES-GCM requires hardware support"); 30 | } 31 | 32 | aesGcm = true; 33 | return this; 34 | } 35 | 36 | public byte[] encrypt(byte[] publicNonce, byte[] message, byte[] additionalData) { 37 | return aesGcm ? 38 | encryptAesGcm(publicNonce, message, additionalData) : 39 | encryptChaChaPoly(publicNonce, message, additionalData); 40 | } 41 | 42 | protected byte[] encryptChaChaPoly(byte[] publicNonce, byte[] message, byte[] additionalData) { 43 | checkLength(publicNonce, CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES); 44 | byte[] ct = zeros(message.length + CRYPTO_AEAD_CHACHA20POLY1305_ABYTES); 45 | isValid(sodium().crypto_aead_chacha20poly1305_encrypt(ct, null, 46 | message, message.length, additionalData, 47 | additionalData.length, null, publicNonce, key), 48 | "Encryption failed"); 49 | 50 | return ct; 51 | } 52 | 53 | protected byte[] encryptAesGcm(byte[] publicNonce, byte[] message, byte[] additionalData) { 54 | checkLength(publicNonce, CRYPTO_AEAD_AES256GCM_NPUBBYTES); 55 | byte[] ct = zeros(message.length + CRYPTO_AEAD_AES256GCM_ABYTES); 56 | isValid(sodium().crypto_aead_aes256gcm_encrypt(ct, null, 57 | message, message.length, additionalData, 58 | additionalData.length, null, publicNonce, key), 59 | "Encryption failed"); 60 | 61 | return ct; 62 | } 63 | 64 | public byte[] decrypt(byte[] publicNonce, byte[] ciphertext, byte[] additionalData) { 65 | return aesGcm ? 66 | decryptAesGcm(publicNonce, ciphertext, additionalData) : 67 | decryptChaChaPoly(publicNonce, ciphertext, additionalData); 68 | } 69 | 70 | protected byte[] decryptChaChaPoly(byte[] publicNonce, byte[] ciphertext, byte[] additionalData) { 71 | checkLength(publicNonce, CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES); 72 | byte[] msg = zeros(ciphertext.length - CRYPTO_AEAD_CHACHA20POLY1305_ABYTES); 73 | isValid(sodium().crypto_aead_chacha20poly1305_decrypt(msg, null, 74 | null, ciphertext, ciphertext.length, additionalData, 75 | additionalData.length, publicNonce, key), 76 | "Decryption failed. Ciphertext failed verification"); 77 | 78 | return msg; 79 | } 80 | 81 | protected byte[] decryptAesGcm(byte[] publicNonce, byte[] ciphertext, byte[] additionalData) { 82 | checkLength(publicNonce, CRYPTO_AEAD_AES256GCM_NPUBBYTES); 83 | byte[] msg = zeros(ciphertext.length - CRYPTO_AEAD_AES256GCM_ABYTES); 84 | isValid(sodium().crypto_aead_aes256gcm_decrypt(msg, null, 85 | null, ciphertext, ciphertext.length, additionalData, 86 | additionalData.length, publicNonce, key), 87 | "Decryption failed. Ciphertext failed verification"); 88 | 89 | return msg; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/crypto/PasswordTest.java: -------------------------------------------------------------------------------- 1 | package org.abstractj.kalium.crypto; 2 | 3 | import org.abstractj.kalium.NaCl; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertTrue; 7 | import static org.abstractj.kalium.encoders.Encoder.HEX; 8 | import static org.abstractj.kalium.fixture.TestVectors.*; 9 | import static org.abstractj.kalium.fixture.TestVectors.PWHASH_MESSAGE; 10 | import static org.abstractj.kalium.fixture.TestVectors.PWHASH_SALT; 11 | import static org.junit.Assert.assertEquals; 12 | import static org.junit.Assert.fail; 13 | 14 | /** 15 | * Created by abstractj on 8/5/15. 16 | */ 17 | public class PasswordTest { 18 | 19 | private final Password password = new Password(); 20 | 21 | @Test 22 | public void testPWHash(){ 23 | String result = password.hash(PWHASH_MESSAGE.getBytes(), 24 | HEX, 25 | PWHASH_SALT.getBytes(), 26 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, 27 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); 28 | assertEquals("Hash is invalid", PWHASH_DIGEST, result); 29 | } 30 | 31 | @Test 32 | public void testPWHashEmptyString(){ 33 | String result = password.hash("".getBytes(), 34 | HEX, 35 | PWHASH_SALT.getBytes(), 36 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, 37 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); 38 | assertEquals("Hash is invalid", PWHASH_DIGEST_EMPTY_STRING, result); 39 | } 40 | 41 | @Test 42 | public void testPWHashNullByte() { 43 | try { 44 | password.hash("\0".getBytes(), 45 | HEX, 46 | PWHASH_SALT.getBytes(), 47 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, 48 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); 49 | } catch (Exception e) { 50 | fail("Should not raise any exception on null byte"); 51 | } 52 | } 53 | 54 | @Test 55 | public void testPWHashStorage(){ 56 | String result = password.hash(PWHASH_MESSAGE.getBytes(), 57 | HEX, 58 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, 59 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); 60 | byte[] hashed = HEX.decode(result); 61 | 62 | // Must return true 63 | boolean verified1 = password.verify(hashed, PWHASH_MESSAGE.getBytes()); 64 | assertTrue("Invalid password", verified1); 65 | 66 | // Must return false since it's an invalid 67 | boolean verified2 = password.verify(hashed, ("i" + PWHASH_MESSAGE).getBytes()); 68 | assertTrue("Valid password", !verified2); 69 | } 70 | 71 | @Test 72 | public void testPWHashKeyDerivation() { 73 | String result = password.hash(NaCl.Sodium.CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES, 74 | PWHASH_MESSAGE.getBytes(), 75 | HEX, 76 | PWHASH_SALT.getBytes(), 77 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, 78 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); 79 | byte[] hashed = HEX.decode(result); 80 | 81 | // Must receive expected size 82 | assertEquals(NaCl.Sodium.CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES, hashed.length); 83 | } 84 | 85 | @Test 86 | public void testPWHashKeyDerivationBytes() { 87 | byte[] key = password.deriveKey(NaCl.Sodium.CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES, 88 | PWHASH_MESSAGE.getBytes(), 89 | PWHASH_SALT.getBytes(), 90 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE, 91 | NaCl.Sodium.CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE); 92 | 93 | // Must receive expected size 94 | assertEquals(NaCl.Sodium.CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES, key.length); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/crypto/Box.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.crypto; 18 | 19 | import org.abstractj.kalium.NaCl; 20 | import org.abstractj.kalium.encoders.Encoder; 21 | import org.abstractj.kalium.keys.PrivateKey; 22 | import org.abstractj.kalium.keys.PublicKey; 23 | 24 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES; 25 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_NONCEBYTES; 26 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES; 27 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES; 28 | import static org.abstractj.kalium.NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES; 29 | import static org.abstractj.kalium.NaCl.sodium; 30 | import static org.abstractj.kalium.crypto.Util.checkLength; 31 | import static org.abstractj.kalium.crypto.Util.isValid; 32 | import static org.abstractj.kalium.crypto.Util.prependZeros; 33 | import static org.abstractj.kalium.crypto.Util.removeZeros; 34 | 35 | /** 36 | * Based on Curve25519XSalsa20Poly1305 and Box classes from rbnacl 37 | */ 38 | public class Box { 39 | 40 | private final byte[] sharedKey; 41 | 42 | public Box(byte[] publicKey, byte[] privateKey) { 43 | checkLength(publicKey, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES); 44 | checkLength(privateKey, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES); 45 | 46 | sharedKey = new byte[NaCl.Sodium.CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BEFORENMBYTES]; 47 | isValid(sodium().crypto_box_curve25519xsalsa20poly1305_beforenm( 48 | sharedKey, publicKey, privateKey), "Key agreement failed"); 49 | } 50 | 51 | public Box(PublicKey publicKey, PrivateKey privateKey) { 52 | this(publicKey.toBytes(), privateKey.toBytes()); 53 | } 54 | 55 | public Box(String publicKey, String privateKey, Encoder encoder) { 56 | this(encoder.decode(publicKey), encoder.decode(privateKey)); 57 | } 58 | 59 | public byte[] encrypt(byte[] nonce, byte[] message) { 60 | checkLength(nonce, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_NONCEBYTES); 61 | byte[] msg = prependZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES, message); 62 | byte[] ct = new byte[msg.length]; 63 | isValid(sodium().crypto_box_curve25519xsalsa20poly1305_afternm(ct, msg, 64 | msg.length, nonce, sharedKey), "Encryption failed"); 65 | return removeZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES, ct); 66 | } 67 | 68 | public byte[] encrypt(String nonce, String message, Encoder encoder) { 69 | return encrypt(encoder.decode(nonce), encoder.decode(message)); 70 | } 71 | 72 | public byte[] decrypt(byte[] nonce, byte[] ciphertext) { 73 | checkLength(nonce, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_NONCEBYTES); 74 | byte[] ct = prependZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES, ciphertext); 75 | byte[] message = new byte[ct.length]; 76 | isValid(sodium().crypto_box_curve25519xsalsa20poly1305_open_afternm( 77 | message, ct, message.length, nonce, sharedKey), 78 | "Decryption failed. Ciphertext failed verification."); 79 | return removeZeros(CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES, message); 80 | } 81 | 82 | public byte[] decrypt(String nonce, String ciphertext, Encoder encoder) { 83 | return decrypt(encoder.decode(nonce), encoder.decode(ciphertext)); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/keys/SigningKeyTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | 23 | import static org.abstractj.kalium.encoders.Encoder.HEX; 24 | import static org.abstractj.kalium.fixture.TestVectors.*; 25 | import static org.junit.Assert.assertEquals; 26 | import static org.junit.Assert.assertTrue; 27 | import static org.junit.Assert.fail; 28 | 29 | public class SigningKeyTest { 30 | 31 | @Test 32 | public void testGenerateSigninKey() throws Exception { 33 | try { 34 | new SigningKey(); 35 | } catch (Exception e) { 36 | fail("Should return a valid key size"); 37 | } 38 | } 39 | 40 | @Test 41 | public void testAcceptsRawValidKey() throws Exception { 42 | try { 43 | byte[] rawKey = HEX.decode(SIGN_PRIVATE); 44 | new SigningKey(rawKey); 45 | } catch (Exception e) { 46 | e.printStackTrace(); 47 | fail("Should return a valid key size"); 48 | } 49 | } 50 | 51 | @Test 52 | public void testAcceptsHexValidKey() throws Exception { 53 | try { 54 | new SigningKey(SIGN_PRIVATE, HEX); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | fail("Should return a valid key size"); 58 | } 59 | } 60 | 61 | @Test 62 | public void testCreateHexValidKey() throws Exception { 63 | try { 64 | new SigningKey(SIGN_PRIVATE, HEX).toString(); 65 | } catch (Exception e) { 66 | e.printStackTrace(); 67 | fail("Should return a valid key size"); 68 | } 69 | } 70 | 71 | @Test 72 | public void testCreateByteValidKey() throws Exception { 73 | try { 74 | new SigningKey(SIGN_PRIVATE, HEX).toBytes(); 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | fail("Should return a valid key size"); 78 | } 79 | } 80 | 81 | @Test(expected = RuntimeException.class) 82 | public void testRejectNullKey() throws Exception { 83 | byte[] key = null; 84 | new SigningKey(key); 85 | fail("Should reject null keys"); 86 | } 87 | 88 | @Test(expected = RuntimeException.class) 89 | public void testRejectShortKey() throws Exception { 90 | byte[] key = "short".getBytes(); 91 | new SigningKey(key); 92 | fail("Should reject short keys"); 93 | } 94 | 95 | @Test 96 | public void testSignMessageAsBytes() throws Exception { 97 | byte[] rawKey = HEX.decode(SIGN_PRIVATE); 98 | byte[] signatureRaw = HEX.decode(SIGN_SIGNATURE); 99 | SigningKey key = new SigningKey(rawKey); 100 | byte[] signedMessage = key.sign(HEX.decode(SIGN_MESSAGE)); 101 | assertTrue("Message sign has failed", Arrays.equals(signatureRaw, signedMessage)); 102 | } 103 | 104 | @Test 105 | public void testSignMessageAsHex() throws Exception { 106 | SigningKey key = new SigningKey(SIGN_PRIVATE, HEX); 107 | String signature = key.sign(SIGN_MESSAGE, HEX); 108 | assertEquals("Message sign has failed", SIGN_SIGNATURE, signature); 109 | } 110 | 111 | @Test 112 | public void testSerializesToHex() throws Exception { 113 | try { 114 | SigningKey key = new SigningKey(SIGN_PRIVATE, HEX); 115 | assertEquals("Correct sign key expected", SIGN_PRIVATE, key.toString()); 116 | } catch (Exception e) { 117 | fail("Should return a valid key size"); 118 | } 119 | } 120 | 121 | @Test 122 | public void testSerializesToBytes() throws Exception { 123 | try { 124 | byte[] rawKey = HEX.decode(SIGN_PRIVATE); 125 | SigningKey key = new SigningKey(SIGN_PRIVATE, HEX); 126 | assertTrue("Correct sign key expected", Arrays.equals(rawKey, 127 | key.toBytes())); 128 | } catch (Exception e) { 129 | fail("Should return a valid key size"); 130 | } 131 | } 132 | 133 | @Test 134 | public void testAccessVerifyKey() { 135 | SigningKey key = new SigningKey(SIGN_PRIVATE, HEX); 136 | VerifyKey v = key.getVerifyKey(); 137 | assertEquals(v.toString(), SIGN_PUBLIC); 138 | } 139 | 140 | @Test 141 | public void testRoundTrip() { 142 | SigningKey key = new SigningKey(SIGN_PRIVATE, HEX); 143 | String signature = key.sign(SIGN_MESSAGE, HEX); 144 | key.getVerifyKey().verify(SIGN_MESSAGE, signature, HEX); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/keys/KeyPairTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.keys; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.Arrays; 23 | 24 | import static org.abstractj.kalium.encoders.Encoder.HEX; 25 | import static org.abstractj.kalium.fixture.TestVectors.BOB_PRIVATE_KEY; 26 | import static org.abstractj.kalium.fixture.TestVectors.BOB_PUBLIC_KEY; 27 | import static org.junit.Assert.assertEquals; 28 | import static org.junit.Assert.assertTrue; 29 | import static org.junit.Assert.fail; 30 | 31 | public class KeyPairTest { 32 | 33 | @Test 34 | public void testGenerateKeyPair() { 35 | try { 36 | KeyPair key = new KeyPair(); 37 | assertTrue(key.getPrivateKey() != null); 38 | assertTrue(key.getPublicKey() != null); 39 | } catch (Exception e) { 40 | fail("Should return a valid key size"); 41 | } 42 | } 43 | 44 | @Test 45 | public void testAcceptsValidKey() { 46 | try { 47 | byte[] rawKey = HEX.decode(BOB_PRIVATE_KEY); 48 | new KeyPair(rawKey); 49 | } catch (Exception e) { 50 | fail("Should not raise any exception"); 51 | } 52 | } 53 | 54 | @Test 55 | public void testAcceptsHexEncodedKey() { 56 | try { 57 | new KeyPair(BOB_PRIVATE_KEY, HEX); 58 | } catch (Exception e) { 59 | fail("Should not raise any exception"); 60 | } 61 | } 62 | 63 | @Test(expected = RuntimeException.class) 64 | public void testRejectNullKey() throws Exception { 65 | byte[] privateKey = null; 66 | new KeyPair(privateKey); 67 | fail("Should reject null keys"); 68 | } 69 | 70 | @Test(expected = RuntimeException.class) 71 | public void testRejectShortKey() throws Exception { 72 | byte[] privateKey = "short".getBytes(); 73 | new KeyPair(privateKey); 74 | fail("Should reject null keys"); 75 | } 76 | 77 | @Test 78 | public void testGeneratePublicKey() throws Exception { 79 | try { 80 | byte[] pk = HEX.decode(BOB_PRIVATE_KEY); 81 | KeyPair key = new KeyPair(pk); 82 | assertTrue(key.getPublicKey() != null); 83 | } catch (Exception e) { 84 | fail("Should return a valid key size"); 85 | } 86 | } 87 | 88 | @Test 89 | public void testPrivateKeyToString() throws Exception { 90 | try { 91 | KeyPair key = new KeyPair(BOB_PRIVATE_KEY, HEX); 92 | assertEquals("Correct private key expected", BOB_PRIVATE_KEY, key.getPrivateKey().toString()); 93 | } catch (Exception e) { 94 | fail("Should return a valid key size"); 95 | } 96 | } 97 | 98 | @Test 99 | public void testPrivateKeyToBytes() throws Exception { 100 | try { 101 | KeyPair key = new KeyPair(BOB_PRIVATE_KEY, HEX); 102 | assertTrue("Correct private key expected", Arrays.equals(HEX.decode(BOB_PUBLIC_KEY), 103 | key.getPublicKey().toBytes())); 104 | } catch (Exception e) { 105 | fail("Should return a valid key size"); 106 | } 107 | } 108 | 109 | @Test 110 | public void testPublicKeyToString() throws Exception { 111 | try { 112 | KeyPair key = new KeyPair(BOB_PRIVATE_KEY, HEX); 113 | assertEquals("Correct public key expected", BOB_PUBLIC_KEY, key.getPublicKey().toString()); 114 | } catch (Exception e) { 115 | fail("Should return a valid key size"); 116 | } 117 | } 118 | 119 | 120 | /** 121 | * TODO: This unit test is a friendly reminder to be investigated 122 | * @see 23 | * This class is thread-safe. 24 | * 25 | * @version $Id$ 26 | * @since 1.1 27 | */ 28 | public class Hex implements Encoder { 29 | 30 | /** 31 | * Used to build output as Hex 32 | */ 33 | private static final char[] DIGITS_LOWER = 34 | {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 35 | 36 | /** 37 | * Used to build output as Hex 38 | */ 39 | private static final char[] DIGITS_UPPER = 40 | {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 41 | 42 | /** 43 | * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The 44 | * returned array will be half the length of the passed array, as it takes two characters to represent any given 45 | * byte. An exception is thrown if the passed char array has an odd number of elements. 46 | * 47 | * @param data An array of characters containing hexadecimal digits 48 | * @return A byte array containing binary data decoded from the supplied char array. 49 | */ 50 | private static byte[] decodeHex(final char[] data) { 51 | 52 | final int len = (data == null) ? 0 : data.length; 53 | 54 | if ((len & 0x01) != 0) { 55 | throw new RuntimeException("Odd number of characters."); 56 | } 57 | 58 | final byte[] out = new byte[len >> 1]; 59 | 60 | // two characters form the hex value. 61 | for (int i = 0, j = 0; j < len; i++) { 62 | int f = toDigit(data[j], j) << 4; 63 | j++; 64 | f = f | toDigit(data[j], j); 65 | j++; 66 | out[i] = (byte) (f & 0xFF); 67 | } 68 | 69 | return out; 70 | } 71 | 72 | @Override 73 | public byte[] decode(final String value) { 74 | 75 | char[] data = value != null ? value.toCharArray() : new char[0]; 76 | return decodeHex(data); 77 | } 78 | 79 | /** 80 | * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. 81 | * The returned array will be double the length of the passed array, as it takes two characters to represent any 82 | * given byte. 83 | * 84 | * @param data a byte[] to convert to Hex characters 85 | * @return A char[] containing hexadecimal characters 86 | */ 87 | private static char[] encodeHex(final byte[] data) { 88 | return encodeHex(data, true); 89 | } 90 | 91 | /** 92 | * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. 93 | * The returned array will be double the length of the passed array, as it takes two characters to represent any 94 | * given byte. 95 | * 96 | * @param data a byte[] to convert to Hex characters 97 | * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase 98 | * @return A char[] containing hexadecimal characters 99 | * @since 1.4 100 | */ 101 | private static char[] encodeHex(final byte[] data, final boolean toLowerCase) { 102 | return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); 103 | } 104 | 105 | /** 106 | * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. 107 | * The returned array will be double the length of the passed array, as it takes two characters to represent any 108 | * given byte. 109 | * 110 | * @param data a byte[] to convert to Hex characters 111 | * @param toDigits the output alphabet 112 | * @return A char[] containing hexadecimal characters 113 | * @since 1.4 114 | */ 115 | private static char[] encodeHex(final byte[] data, final char[] toDigits) { 116 | final int l = data.length; 117 | final char[] out = new char[l << 1]; 118 | // two characters form the hex value. 119 | for (int i = 0, j = 0; i < l; i++) { 120 | out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; 121 | out[j++] = toDigits[0x0F & data[i]]; 122 | } 123 | return out; 124 | } 125 | 126 | /** 127 | * Converts an array of bytes into a String representing the hexadecimal values of each byte in order. The returned 128 | * String will be double the length of the passed array, as it takes two characters to represent any given byte. 129 | * 130 | * @param data a byte[] to convert to Hex characters 131 | * @return A String containing hexadecimal characters 132 | * @since 1.4 133 | */ 134 | @Override 135 | public String encode(final byte[] data) { 136 | return new String(encodeHex(data)); 137 | } 138 | 139 | /** 140 | * Converts a hexadecimal character to an integer. 141 | * 142 | * @param ch A character to convert to an integer digit 143 | * @param index The index of the character in the source 144 | * @return An integer 145 | */ 146 | private static int toDigit(final char ch, final int index) { 147 | final int digit = Character.digit(ch, 16); 148 | if (digit == -1) { 149 | throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index); 150 | } 151 | return digit; 152 | } 153 | 154 | /** 155 | * Returns a string representation of the object, which includes the charset name. 156 | * 157 | * @return a string representation of the object. 158 | */ 159 | @Override 160 | public String toString() { 161 | return super.toString() + "[charsetName=" + CHARSET + "]"; 162 | } 163 | } -------------------------------------------------------------------------------- /src/test/java/org/abstractj/kalium/fixture/TestVectors.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium.fixture; 18 | 19 | public class TestVectors { 20 | 21 | /** 22 | * HMAC SHA512256 test vectors 23 | */ 24 | 25 | public static final String AUTH_KEY = "eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880"; 26 | public static final String AUTH_MESSAGE = "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a" + 27 | "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738" + 28 | "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da" + 29 | "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74" + 30 | "e355a5"; 31 | public static final String AUTH_HMAC_SHA512256 = "b2a31b8d4e01afcab2ee545b5caf4e3d212a99d7b3a116a97cec8e83c32e107d"; 32 | 33 | /** 34 | * SHA256 test vectors 35 | */ 36 | 37 | public static final String SHA256_MESSAGE = "My Bonnie lies over the ocean, my Bonnie lies over the sea"; 38 | public static final String SHA256_DIGEST = "d281d10296b7bde20df3f3f4a6d1bdb513f4aa4ccb0048c7b2f7f5786b4bcb77"; 39 | public static final String SHA256_DIGEST_EMPTY_STRING = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; 40 | 41 | /** 42 | * SHA512 test vectors 43 | */ 44 | 45 | public static final String SHA512_MESSAGE = "My Bonnie lies over the ocean, Oh bring back my Bonnie to me"; 46 | public static final String SHA512_DIGEST = "2823e0373001b5f3aa6db57d07bc588324917fc221dd27975613942d7f2e19bf4" + 47 | "44654c8b9f4f9cb908ef15f2304522e60e9ced3fdec66e34bc2afb52be6ad1c"; 48 | public static final String SHA512_DIGEST_EMPTY_STRING = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921" + 49 | "d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; 50 | 51 | /** 52 | * Blake2 test vectors 53 | */ 54 | 55 | public static final String Blake2_MESSAGE = "The quick brown fox jumps over the lazy dog"; 56 | public static final String Blake2_DIGEST = "01718cec35cd3d796dd00020e0bfecb473ad23457d063b75eff29c0ffa2e58a9"; 57 | public static final String Blake2_DIGEST_EMPTY_STRING = "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8"; 58 | public static final String Blake2_KEY = "This is a super secret key. Ssshh!"; 59 | public static final String Blake2_SALT = "0123456789abcdef"; 60 | public static final String Blake2_PERSONAL = "fedcba9876543210"; 61 | public static final String Blake2_DIGEST_WITH_SALT_PERSONAL = "108e81d0c7b0487de45c54554ea35b427f886b098d792497c6a803bbac7a5f7c"; 62 | 63 | /** 64 | * SipHash-2-4 test vectors 65 | */ 66 | 67 | public static final String SIPHASH24_KEY = "000102030405060708090a0b0c0d0e0f"; 68 | public static final String SIPHASH24_MESSAGE = "000102030405060708090a0b0c0d0e"; 69 | public static final String SIPHASH24_DIGEST = "e545be4961ca29a1"; 70 | public static final String SIPHASH24_DIGEST_EMPTY_STRING = "310e0edd47db6f72"; 71 | 72 | /** 73 | * pwhash test vectors 74 | * */ 75 | 76 | public static final String PWHASH_MESSAGE = "Correct Horse Battery Staple"; 77 | public static final String PWHASH_SALT = "[<~A 32-bytes salt for scrypt~>]"; 78 | public static final String PWHASH_DIGEST = "a2ec8a8ee744e0ff2c26d4fc198ddf7c0cd1460b5b6729e0d8518b6577c69acd412491f0913737e64c5c9136c04731545e756e0a9be35f55337e446c6bbc3a3f"; 79 | public static final String PWHASH_DIGEST_EMPTY_STRING = "f8b1543b940c7898ce90261d07f5193cb0570081e47b01610c043b8091666e12585ab9844edb189624c2ba662ca7478cfbed9f38fe1066b7ce583a3321470424"; 80 | 81 | 82 | /** 83 | * Curve25519 test vectors 84 | */ 85 | 86 | public static final String BOB_PRIVATE_KEY = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"; 87 | public static final String BOB_PUBLIC_KEY = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"; 88 | 89 | public static final String ALICE_PRIVATE_KEY = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"; 90 | public static final String ALICE_PUBLIC_KEY = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"; 91 | public static final String ALICE_MULT_BOB = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"; 92 | 93 | public static final String BOX_NONCE = "69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37"; 94 | public static final String BOX_MESSAGE = "be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffc" + 95 | "e5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb31" + 96 | "0e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde" + 97 | "048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f93776384864" + 98 | "5e0705"; 99 | public static final String BOX_CIPHERTEXT = "f3ffc7703f9400e52a7dfb4b3d3305d98e993b9f48681273c29650ba32fc76ce" + 100 | "48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c972" + 101 | "71d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae" + 102 | "90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b3" + 103 | "7973f622a43d14a6599b1f654cb45a74e355a5"; 104 | 105 | public static final String SECRET_KEY = "1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389"; 106 | 107 | public static final String SIGN_PRIVATE = "b18e1d0045995ec3d010c387ccfeb984d783af8fbb0f40fa7db126d889f6dadd"; 108 | public static final String SIGN_MESSAGE = "916c7d1d268fc0e77c1bef238432573c39be577bbea0998936add2b50a653171" + 109 | "ce18a542b0b7f96c1691a3be6031522894a8634183eda38798a0c5d5d79fbd01" + 110 | "dd04a8646d71873b77b221998a81922d8105f892316369d5224c9983372d2313" + 111 | "c6b1f4556ea26ba49d46e8b561e0fc76633ac9766e68e21fba7edca93c4c7460" + 112 | "376d7f3ac22ff372c18f613f2ae2e856af40"; 113 | public static final String SIGN_SIGNATURE = "6bd710a368c1249923fc7a1610747403040f0cc30815a00f9ff548a896bbda0b" + 114 | "4eb2ca19ebcf917f0f34200a9edbad3901b64ab09cc5ef7b9bcc3c40c0ff7509"; 115 | public static final String SIGN_PUBLIC = "77f48b59caeda77751ed138b0ec667ff50f8768c25d48309a8f386a2bad187fb"; 116 | 117 | 118 | 119 | /** 120 | * AEAD test vectors 121 | */ 122 | 123 | public static final String AEAD_KEY = "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007"; 124 | public static final String AEAD_MESSAGE = "86d09974840bded2a5ca"; 125 | public static final String AEAD_NONCE = "cd7cf67be39c794a"; 126 | public static final String AEAD_AD = "87e229d4500845a079c0"; 127 | public static final String AEAD_CT = "e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6"; 128 | } 129 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.abstractj.kalium 6 | kalium 7 | 0.8.1-SNAPSHOT 8 | jar 9 | 10 | kalium 11 | http://github.com/abstractj/kalium 12 | 13 | 14 | org.sonatype.oss 15 | oss-parent 16 | 7 17 | 18 | 19 | 20 | UTF-8 21 | 22 | 23 | 2.0.5 24 | 4.11 25 | 26 | 27 | 1.6 28 | 29 | 30 | 3.0.5 31 | 32 | 33 | 2.6 34 | 2.3.2 35 | 2.1.2 36 | 2.8.1 37 | 1.1 38 | 2.4 39 | 1.4 40 | 41 | 42 | 43 | 44 | scm:git:git@github.com:abstractj/kalium.git 45 | scm:git:git@github.com:abstractj/kalium.git 46 | https://github.com/abstractj/kalium 47 | HEAD 48 | 49 | 50 | 51 | 52 | The Apache Software License, Version 2.0 53 | http://www.apache.org/licenses/LICENSE-2.0.txt 54 | repo 55 | 56 | 57 | 58 | 59 | 60 | abstractj 61 | Bruno Oliveira 62 | http://abstractj.org 63 | bruno@abstractj.org 64 | 65 | Software Developer 66 | 67 | 68 | 69 | qmx 70 | Douglas Campos 71 | http://github.com/qmx 72 | qmx@qmx.me 73 | 74 | Software Developer 75 | 76 | 77 | 78 | 79 | 80 | 81 | com.github.jnr 82 | jnr-ffi 83 | ${jnr-ffi.version} 84 | 85 | 86 | junit 87 | junit 88 | ${junit.version} 89 | test 90 | 91 | 92 | 93 | 94 | 95 | 96 | org.apache.maven.plugins 97 | maven-resources-plugin 98 | ${resources-plugin.version} 99 | 100 | ${project.build.sourceEncoding} 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-compiler-plugin 106 | ${compiler-plugin.version} 107 | 108 | ${jdk.version} 109 | ${jdk.version} 110 | ${project.build.sourceEncoding} 111 | 112 | 113 | 114 | org.apache.maven.plugins 115 | maven-source-plugin 116 | ${source-plugin.version} 117 | 118 | 119 | attach-sources 120 | verify 121 | 122 | jar-no-fork 123 | 124 | 125 | 126 | 127 | 128 | org.apache.maven.plugins 129 | maven-javadoc-plugin 130 | ${javadoc-plugin.version} 131 | 132 | private 133 | true 134 | 135 | 136 | 137 | attach-sources 138 | verify 139 | 140 | jar 141 | 142 | 143 | 144 | 145 | 146 | org.apache.maven.plugins 147 | maven-enforcer-plugin 148 | ${enforcer-plugin.version} 149 | 150 | 151 | enforce-maven 152 | 153 | enforce 154 | 155 | 156 | 157 | 158 | ${maven.version} 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | org.apache.maven.plugins 167 | maven-release-plugin 168 | ${release-plugin.version} 169 | 170 | false 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | release-sign-artifacts 179 | 180 | 181 | performRelease 182 | true 183 | 184 | 185 | 186 | 187 | 188 | org.apache.maven.plugins 189 | maven-gpg-plugin 190 | ${gpg-plugin.version} 191 | 192 | 193 | sign-artifacts 194 | verify 195 | 196 | sign 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | jdk8 206 | 207 | [1.8,) 208 | 209 | 210 | 211 | 212 | org.apache.maven.plugins 213 | maven-javadoc-plugin 214 | ${javadoc-plugin.version} 215 | 216 | private 217 | true 218 | -Xdoclint:none 219 | 220 | 221 | 222 | attach-sources 223 | verify 224 | 225 | jar 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /src/main/java/org/abstractj/kalium/NaCl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 Bruno Oliveira, and individual contributors 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.abstractj.kalium; 18 | 19 | import jnr.ffi.LibraryLoader; 20 | import jnr.ffi.Platform; 21 | import jnr.ffi.annotations.In; 22 | import jnr.ffi.annotations.Out; 23 | import jnr.ffi.byref.LongLongByReference; 24 | import jnr.ffi.types.u_int64_t; 25 | 26 | public class NaCl { 27 | 28 | public static Sodium sodium() { 29 | Sodium sodium = SingletonHolder.SODIUM_INSTANCE; 30 | checkVersion(sodium); 31 | return sodium; 32 | } 33 | 34 | private static final String LIBRARY_NAME = libraryName(); 35 | 36 | private static String libraryName() { 37 | switch (Platform.getNativePlatform().getOS()) { 38 | case WINDOWS: 39 | return "libsodium"; 40 | default: 41 | return "sodium"; 42 | } 43 | } 44 | 45 | private static final class SingletonHolder { 46 | public static final Sodium SODIUM_INSTANCE = 47 | LibraryLoader.create(Sodium.class) 48 | .search("/usr/local/lib") 49 | .search("/opt/local/lib") 50 | .search("lib") 51 | .load(LIBRARY_NAME); 52 | 53 | } 54 | 55 | public static final Integer[] MIN_SUPPORTED_VERSION = 56 | new Integer[] { 1, 0, 3 }; 57 | 58 | private static boolean versionSupported = false; 59 | 60 | private static final void checkVersion(Sodium lib) { 61 | if (!versionSupported) { 62 | String[] version = lib.sodium_version_string().split("\\."); 63 | versionSupported = version.length >= 3 && 64 | MIN_SUPPORTED_VERSION[0] <= new Integer(version[0]) && 65 | MIN_SUPPORTED_VERSION[1] <= new Integer(version[1]) && 66 | MIN_SUPPORTED_VERSION[2] <= new Integer(version[2]); 67 | } 68 | if (!versionSupported) { 69 | String message = String.format("Unsupported libsodium version: %s. Please update", 70 | lib.sodium_version_string()); 71 | throw new UnsupportedOperationException(message); 72 | } 73 | } 74 | 75 | private NaCl() { 76 | } 77 | 78 | public interface Sodium { 79 | 80 | /** 81 | * This function isn't thread safe. Be sure to call it once, and before 82 | * performing other operations. 83 | * 84 | * Check libsodium's documentation for more info. 85 | */ 86 | int sodium_init(); 87 | 88 | String sodium_version_string(); 89 | 90 | // --------------------------------------------------------------------- 91 | // Generating Random Data 92 | 93 | void randombytes(@Out byte[] buffer, @In @u_int64_t int size); 94 | 95 | // --------------------------------------------------------------------- 96 | // Secret-key cryptography: Authenticated encryption 97 | 98 | /** 99 | * @deprecated use CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES 100 | */ 101 | @Deprecated 102 | int XSALSA20_POLY1305_SECRETBOX_KEYBYTES = 32; 103 | 104 | /** 105 | * @deprecated use CRYPTO_SECRETBOX_XSALSA20POLY1305_NONCEBYTES 106 | */ 107 | @Deprecated 108 | int XSALSA20_POLY1305_SECRETBOX_NONCEBYTES = 24; 109 | 110 | int CRYPTO_SECRETBOX_XSALSA20POLY1305_KEYBYTES = 32; 111 | 112 | int CRYPTO_SECRETBOX_XSALSA20POLY1305_NONCEBYTES = 24; 113 | 114 | int crypto_secretbox_xsalsa20poly1305( 115 | @Out byte[] ct, @In byte[] msg, @In @u_int64_t int length, 116 | @In byte[] nonce, @In byte[] key); 117 | 118 | int crypto_secretbox_xsalsa20poly1305_open( 119 | @Out byte[] message, @In byte[] ct, @In @u_int64_t int length, 120 | @In byte[] nonce, @In byte[] key); 121 | 122 | // --------------------------------------------------------------------- 123 | // Secret-key cryptography: Authentication 124 | 125 | /** 126 | * @deprecated use CRYPTO_AUTH_HMACSHA512256_BYTESS 127 | */ 128 | @Deprecated 129 | int HMACSHA512256_BYTES = 32; 130 | 131 | /** 132 | * @deprecated use CRYPTO_AUTH_HMACSHA512256_KEYBYTESS 133 | */ 134 | @Deprecated 135 | int HMACSHA512256_KEYBYTES = 32; 136 | 137 | int CRYPTO_AUTH_HMACSHA512256_BYTES = 32; 138 | 139 | int CRYPTO_AUTH_HMACSHA512256_KEYBYTES = 32; 140 | 141 | int crypto_auth_hmacsha512256( 142 | @Out byte[] mac, @In byte[] message, @In @u_int64_t int sizeof, 143 | @In byte[] key); 144 | 145 | int crypto_auth_hmacsha512256_verify( 146 | @In byte[] mac, @In byte[] message, @In @u_int64_t int sizeof, 147 | @In byte[] key); 148 | 149 | // --------------------------------------------------------------------- 150 | // Secret-key cryptography: AEAD 151 | 152 | int CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES = 32; 153 | 154 | int CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES = 8; 155 | 156 | int CRYPTO_AEAD_CHACHA20POLY1305_ABYTES = 16; 157 | 158 | int crypto_aead_chacha20poly1305_encrypt( 159 | @Out byte[] ct, @Out LongLongByReference ctLength, 160 | @In byte[] message, @In @u_int64_t int messageLength, 161 | @In byte[] additionalData, @In @u_int64_t int adLength, 162 | @In byte[] nsec, @In byte[] npub, @In byte[] key); 163 | 164 | int crypto_aead_chacha20poly1305_decrypt( 165 | @Out byte[] message, @Out LongLongByReference messageLength, 166 | @In byte[] nsec, @In byte[] ct, @In @u_int64_t int ctLength, 167 | @In byte[] additionalData, @In @u_int64_t int adLength, 168 | @In byte[] npub, @In byte[] key); 169 | 170 | // --------------------------------------------------------------------- 171 | // Public-key cryptography: Authenticated encryption 172 | 173 | /** 174 | * @deprecated use CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES 175 | */ 176 | @Deprecated 177 | int PUBLICKEY_BYTES = 32; 178 | 179 | /** 180 | * @deprecated use CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTESS 181 | */ 182 | @Deprecated 183 | int SECRETKEY_BYTES = 32; 184 | 185 | /** 186 | * @deprecated use CRYPTO_BOX_CURVE25519XSALSA20POLY1305_NONCEBYTES 187 | */ 188 | @Deprecated 189 | int NONCE_BYTES = 24; 190 | 191 | /** 192 | * @deprecated use CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTESS 193 | */ 194 | @Deprecated 195 | int ZERO_BYTES = 32; 196 | 197 | /** 198 | * @deprecated use CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES 199 | */ 200 | @Deprecated 201 | int BOXZERO_BYTES = 16; 202 | 203 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES = 32; 204 | 205 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_SECRETKEYBYTES = 32; 206 | 207 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES = 32; 208 | 209 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES = 16; 210 | 211 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_MACBYTES = 212 | CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES - 213 | CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES; 214 | 215 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_NONCEBYTES = 24; 216 | 217 | int CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BEFORENMBYTES = 32; 218 | 219 | int crypto_scalarmult_base( 220 | @Out byte[] publicKey, @In byte[] secretKey); 221 | 222 | int crypto_box_curve25519xsalsa20poly1305_keypair( 223 | @Out byte[] publicKey, @Out byte[] secretKey); 224 | 225 | int crypto_box_curve25519xsalsa20poly1305_beforenm( 226 | @Out byte[] sharedkey, @In byte[] publicKey, 227 | @In byte[] privateKey); 228 | 229 | int crypto_box_curve25519xsalsa20poly1305( 230 | @Out byte[] ct, @In byte[] msg, @In @u_int64_t int length, 231 | @In byte[] nonce, @In byte[] publicKey, @In byte[] privateKey); 232 | 233 | int crypto_box_curve25519xsalsa20poly1305_afternm( 234 | @Out byte[] ct, @In byte[] msg, @In @u_int64_t int length, 235 | @In byte[] nonce, @In byte[] shared); 236 | 237 | int crypto_box_curve25519xsalsa20poly1305_open( 238 | @Out byte[] message, @In byte[] ct, @In @u_int64_t int length, 239 | @In byte[] nonce, @In byte[] publicKey, @In byte[] privateKey); 240 | 241 | int crypto_box_curve25519xsalsa20poly1305_open_afternm( 242 | @Out byte[] message, @In byte[] ct, @In @u_int64_t int length, 243 | @In byte[] nonce, @In byte[] shared); 244 | 245 | // --------------------------------------------------------------------- 246 | // Public-key cryptography: Public-key signatures 247 | 248 | /** 249 | * @deprecated use the documented CRYPTO_SIGN_ED25519_BYTES. 250 | */ 251 | @Deprecated 252 | int SIGNATURE_BYTES = 64; 253 | 254 | int CRYPTO_SIGN_ED25519_PUBLICKEYBYTES = 32; 255 | 256 | int CRYPTO_SIGN_ED25519_SECRETKEYBYTES = 64; 257 | 258 | int CRYPTO_SIGN_ED25519_BYTES = 64; 259 | 260 | int crypto_sign_ed25519_seed_keypair( 261 | @Out byte[] publicKey, @Out byte[] secretKey, @In byte[] seed); 262 | 263 | int crypto_sign_ed25519( 264 | @Out byte[] buffer, @Out LongLongByReference bufferLen, 265 | @In byte[] message, @In @u_int64_t int length, 266 | @In byte[] secretKey); 267 | 268 | int crypto_sign_ed25519_open( 269 | @Out byte[] buffer, @Out LongLongByReference bufferLen, 270 | @In byte[] sigAndMsg, @In @u_int64_t int length, 271 | @In byte[] key); 272 | 273 | int crypto_sign_ed25519_detached(@Out byte[] sig, @Out LongLongByReference sigLen, 274 | @In byte[] message, @In @u_int64_t int length, 275 | @In byte[] secretKey); 276 | 277 | int crypto_sign_ed25519_verify_detached(@In byte[] sig, 278 | @In byte[] message, @In @u_int64_t int length, 279 | @In byte[] key); 280 | 281 | // --------------------------------------------------------------------- 282 | // Public-key cryptography: Sealed boxes 283 | 284 | int CRYPTO_BOX_SEALBYTES = 285 | CRYPTO_BOX_CURVE25519XSALSA20POLY1305_PUBLICKEYBYTES + 286 | CRYPTO_BOX_CURVE25519XSALSA20POLY1305_MACBYTES; 287 | 288 | int crypto_box_seal( 289 | @Out byte[] ct, @In byte[] message, @In @u_int64_t int length, 290 | @In byte[] publicKey); 291 | 292 | int crypto_box_seal_open( 293 | @Out byte[] message, @In byte[] c, @In @u_int64_t int length, 294 | @In byte[] publicKey, @In byte[] privateKey); 295 | 296 | // --------------------------------------------------------------------- 297 | // Hashing: Generic hashing 298 | 299 | /** 300 | * @deprecated use CRYPTO_GENERICHASH_BLAKE2B_BYTES_MAX. Note that 301 | * the Libsodium standard value is '32' and not '64' as defined here. 302 | */ 303 | @Deprecated 304 | int BLAKE2B_OUTBYTES = 64; 305 | 306 | int CRYPTO_GENERICHASH_BLAKE2B_BYTES = 32; 307 | 308 | int CRYPTO_GENERICHASH_BLAKE2B_BYTES_MIN = 16; 309 | 310 | int CRYPTO_GENERICHASH_BLAKE2B_BYTES_MAX = 64; 311 | 312 | int CRYPTO_GENERICHASH_BLAKE2B_KEYBYTES = 32; 313 | 314 | int CRYPTO_GENERICHASH_BLAKE2B_KEYBYTES_MIN = 16; 315 | 316 | int CRYPTO_GENERICHASH_BLAKE2B_KEYBYTES_MAX = 64; 317 | 318 | int crypto_generichash_blake2b( 319 | @Out byte[] buffer, @In @u_int64_t int outLen, 320 | @In byte[] message, @u_int64_t int messageLen, @In byte[] key, 321 | @In @u_int64_t int keyLen); 322 | 323 | int crypto_generichash_blake2b_salt_personal( 324 | @Out byte[] buffer, @In @u_int64_t int outLen, 325 | @In byte[] message, @u_int64_t int messageLen, @In byte[] key, 326 | @In @u_int64_t int keyLen, @In byte[] salt, 327 | @In byte[] personal); 328 | 329 | // --------------------------------------------------------------------- 330 | // Hashing: Short-input hashing 331 | 332 | int CRYPTO_SHORTHASH_SIPHASH24_BYTES = 8; 333 | 334 | int CRYPTO_SHORTHASH_SIPHASH24_KEYBYTES = 16; 335 | 336 | int crypto_shorthash_siphash24(@Out byte[] out, @In byte[] in, @u_int64_t int inLen, @In byte[] key); 337 | 338 | // --------------------------------------------------------------------- 339 | // Password hashing 340 | 341 | /** 342 | * @deprecated use CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRBYTES 343 | */ 344 | @Deprecated 345 | int PWHASH_SCRYPTSALSA208SHA256_STRBYTES = 102; 346 | 347 | /** 348 | * @deprecated use CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OUTBYTES 349 | */ 350 | @Deprecated 351 | int PWHASH_SCRYPTSALSA208SHA256_OUTBYTES = 64; 352 | 353 | /** 354 | * @deprecated use CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE 355 | */ 356 | @Deprecated 357 | int PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE = 524288; 358 | 359 | /** 360 | * @deprecated use CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE 361 | */ 362 | @Deprecated 363 | int PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE = 16777216; 364 | 365 | 366 | int CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRBYTES = 102; 367 | 368 | int CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OUTBYTES = 64; 369 | 370 | int CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE = 524288; 371 | 372 | int CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE = 16777216; 373 | 374 | int crypto_pwhash_scryptsalsa208sha256( 375 | @Out byte[] buffer, @In @u_int64_t int outlen, 376 | @In byte[] passwd, 377 | @In @u_int64_t int passwdlen, @In byte[] salt, 378 | @In @u_int64_t long opslimit, @In @u_int64_t long memlimit); 379 | 380 | int crypto_pwhash_scryptsalsa208sha256_str( 381 | @Out byte[] buffer, @In byte[] passwd, 382 | @In @u_int64_t int passwdlen, @In @u_int64_t long opslimit, 383 | @In @u_int64_t long memlimit); 384 | 385 | int crypto_pwhash_scryptsalsa208sha256_str_verify( 386 | @In byte[] buffer, @In byte[] passwd, 387 | @In @u_int64_t int passwdlen); 388 | 389 | // --------------------------------------------------------------------- 390 | // Advanced: AES256-GCM 391 | 392 | int CRYPTO_AEAD_AES256GCM_KEYBYTES = 32; 393 | 394 | int CRYPTO_AEAD_AES256GCM_NPUBBYTES = 12; 395 | 396 | int CRYPTO_AEAD_AES256GCM_ABYTES = 16; 397 | 398 | /** 399 | * @return 1 if the current CPU supports the AES256-GCM implementation, 400 | * and 0 if it doesn't. 401 | */ 402 | int crypto_aead_aes256gcm_is_available(); 403 | 404 | int crypto_aead_aes256gcm_encrypt( 405 | @Out byte[] ct, @Out LongLongByReference ctLen, @In byte[] msg, 406 | @In @u_int64_t int msgLen, @In byte[] ad, 407 | @In @u_int64_t int adLen, @In byte[] nsec, @In byte[] npub, 408 | @In byte[] key); 409 | 410 | int crypto_aead_aes256gcm_decrypt( 411 | @Out byte[] msg, @Out LongLongByReference msgLen, @In byte[] nsec, 412 | @In byte[] ct, @In @u_int64_t int ctLen, @In byte[] ad, 413 | @In @u_int64_t int adLen, @In byte[] npub, @In byte[] key); 414 | 415 | int crypto_aead_aes256gcm_statebytes(); 416 | 417 | int crypto_aead_aes256gcm_beforenm( 418 | @Out byte[] state, @In byte[] key); 419 | 420 | int crypto_aead_aes256gcm_encrypt_afternm( 421 | @Out byte[] ct, @Out LongLongByReference ctLen, @In byte[] msg, 422 | @In @u_int64_t int msgLen, @In byte[] ad, 423 | @In @u_int64_t int adLen, @In byte[] nsec, @In byte[] npub, 424 | @In @Out byte[] state); 425 | 426 | int crypto_aead_aes256gcm_decrypt_afternm( 427 | @Out byte[] ct, @Out LongLongByReference ctLen, @In byte[] msg, 428 | @In @u_int64_t int msgLen, @In byte[] ad, 429 | @In @u_int64_t int adLen, @In byte[] nsec, @In byte[] npub, 430 | @In @Out byte[] state); 431 | 432 | // --------------------------------------------------------------------- 433 | // Advanced: SHA-2 434 | 435 | /** 436 | * @deprecated use CRYPTO_HASH_SHA256_BYTES 437 | */ 438 | int SHA256BYTES = 32; 439 | 440 | /** 441 | * @deprecated use CRYPTO_HASH_SHA512_BYTES 442 | */ 443 | int SHA512BYTES = 64; 444 | 445 | int CRYPTO_HASH_SHA256_BYTES = 32; 446 | 447 | int crypto_hash_sha256( 448 | @Out byte[] buffer, @In byte[] message, 449 | @In @u_int64_t int sizeof); 450 | 451 | int CRYPTO_HASH_SHA512_BYTES = 64; 452 | 453 | int crypto_hash_sha512( 454 | @Out byte[] buffer, @In byte[] message, 455 | @In @u_int64_t int sizeof); 456 | 457 | // --------------------------------------------------------------------- 458 | // Advanced: HMAC-SHA-2 459 | 460 | // TODO 461 | 462 | // --------------------------------------------------------------------- 463 | // Advanced: One-time authentication 464 | 465 | // TODO 466 | 467 | // --------------------------------------------------------------------- 468 | // Advanced: Diffie-Hellman 469 | 470 | int CRYPTO_SCALARMULT_CURVE25519_SCALARBYTES = 32; 471 | 472 | int CRYPTO_SCALARMULT_CURVE25519_BYTES = 32; 473 | 474 | int crypto_scalarmult_curve25519( 475 | @Out byte[] result, @In byte[] intValue, @In byte[] point); 476 | 477 | // --------------------------------------------------------------------- 478 | // Advanced: Stream ciphers: ChaCha20 479 | 480 | // TODO 481 | 482 | // --------------------------------------------------------------------- 483 | // Advanced: Stream ciphers: Salsa20 484 | 485 | int CRYPTO_STREAM_KEYBYTES = 32; 486 | 487 | int CRYPTO_STREAM_NONCEBYTES = 24; 488 | 489 | int crypto_stream_xor( 490 | @Out byte[] result, @In byte[] message, 491 | @In @u_int64_t int mlen, 492 | @In byte[] nonce, @In byte[] key); 493 | 494 | // --------------------------------------------------------------------- 495 | // Advanced: Stream ciphers: XSalsa20 496 | 497 | // TODO 498 | 499 | // --------------------------------------------------------------------- 500 | // Advanced: Ed25519 to Curve25519 501 | 502 | } 503 | 504 | /** 505 | * This is a Java synchronized wrapper around libsodium's init function. 506 | * LibSodium's init function is not thread-safe. 507 | * 508 | * Check libsodium's documentation for more info. 509 | */ 510 | public static synchronized int init() { 511 | return sodium().sodium_init(); 512 | } 513 | } 514 | --------------------------------------------------------------------------------