From 868b42ba028ad968185742a3692627c3b67079a2 Mon Sep 17 00:00:00 2001 From: Omer Akram Date: Thu, 14 Mar 2019 01:42:14 +0500 Subject: [PATCH 1/6] Add preliminary (untested) SealedBox support --- .../org/libsodium/jni/crypto/SealedBox.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/org/libsodium/jni/crypto/SealedBox.java diff --git a/src/main/java/org/libsodium/jni/crypto/SealedBox.java b/src/main/java/org/libsodium/jni/crypto/SealedBox.java new file mode 100644 index 0000000..2b7b9ac --- /dev/null +++ b/src/main/java/org/libsodium/jni/crypto/SealedBox.java @@ -0,0 +1,52 @@ +package org.libsodium.jni.crypto; + +import org.libsodium.jni.Sodium; +import org.libsodium.jni.encoders.Encoder; + +import static org.libsodium.jni.SodiumConstants.SEAL_BYTES; +import static org.libsodium.jni.crypto.Util.isValid; + +public class SealedBox { + + private byte[] publicKey; + private byte[] privateKey; + + public SealedBox(byte[] publicKey) { + this.publicKey = publicKey; + this.privateKey = null; + } + + public SealedBox(String publicKey, Encoder encoder) { + this(encoder.decode(publicKey)); + } + + public SealedBox(byte[] publicKey, byte[] privateKey) { + this.publicKey = publicKey; + this.privateKey = privateKey; + } + + public SealedBox(String publicKey, String privateKey, Encoder encoder) { + this(encoder.decode(publicKey), encoder.decode(privateKey)); + } + + public byte[] encrypt(byte[] message) { + if (publicKey == null) + throw new RuntimeException("Encryption failed. Public key not available."); + byte[] ct = new byte[message.length + SEAL_BYTES]; + isValid(Sodium.crypto_box_seal( + ct, message, message.length, publicKey), + "Encryption failed"); + return ct; + } + + public byte[] decrypt(byte[] ciphertext) { + if (privateKey == null) + throw new RuntimeException("Decryption failed. Private key not available."); + + byte[] message = new byte[ciphertext.length - SEAL_BYTES]; + isValid(Sodium.crypto_box_seal_open( + message, ciphertext, ciphertext.length, publicKey, privateKey), + "Decryption failed. Ciphertext failed verification"); + return message; + } +} From 4dc2e93fbf4ee7f3412c25db6791ceb2fd261512 Mon Sep 17 00:00:00 2001 From: Omer Akram Date: Thu, 14 Mar 2019 02:23:43 +0500 Subject: [PATCH 2/6] use the sodium() method which ensures thins are initialized --- src/main/java/org/libsodium/jni/crypto/SealedBox.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/libsodium/jni/crypto/SealedBox.java b/src/main/java/org/libsodium/jni/crypto/SealedBox.java index 2b7b9ac..f4fa6a7 100644 --- a/src/main/java/org/libsodium/jni/crypto/SealedBox.java +++ b/src/main/java/org/libsodium/jni/crypto/SealedBox.java @@ -1,8 +1,8 @@ package org.libsodium.jni.crypto; -import org.libsodium.jni.Sodium; import org.libsodium.jni.encoders.Encoder; +import static org.libsodium.jni.NaCl.sodium; import static org.libsodium.jni.SodiumConstants.SEAL_BYTES; import static org.libsodium.jni.crypto.Util.isValid; @@ -33,7 +33,7 @@ public byte[] encrypt(byte[] message) { if (publicKey == null) throw new RuntimeException("Encryption failed. Public key not available."); byte[] ct = new byte[message.length + SEAL_BYTES]; - isValid(Sodium.crypto_box_seal( + isValid(sodium().crypto_box_seal( ct, message, message.length, publicKey), "Encryption failed"); return ct; @@ -44,7 +44,7 @@ public byte[] decrypt(byte[] ciphertext) { throw new RuntimeException("Decryption failed. Private key not available."); byte[] message = new byte[ciphertext.length - SEAL_BYTES]; - isValid(Sodium.crypto_box_seal_open( + isValid(sodium().crypto_box_seal_open( message, ciphertext, ciphertext.length, publicKey, privateKey), "Decryption failed. Ciphertext failed verification"); return message; From 8c6ebbda14bb2683322b5a00eab9ebcca5ccfa90 Mon Sep 17 00:00:00 2001 From: Omer Akram Date: Sat, 23 Mar 2019 00:33:05 +0500 Subject: [PATCH 3/6] Ensure public and private keys are not null when constructing --- .../org/libsodium/jni/crypto/SealedBox.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/libsodium/jni/crypto/SealedBox.java b/src/main/java/org/libsodium/jni/crypto/SealedBox.java index f4fa6a7..ea6812f 100644 --- a/src/main/java/org/libsodium/jni/crypto/SealedBox.java +++ b/src/main/java/org/libsodium/jni/crypto/SealedBox.java @@ -11,7 +11,10 @@ public class SealedBox { private byte[] publicKey; private byte[] privateKey; - public SealedBox(byte[] publicKey) { + public SealedBox(byte[] publicKey) throws IllegalArgumentException { + if (publicKey == null) { + throw new IllegalArgumentException("Public key must not be null"); + } this.publicKey = publicKey; this.privateKey = null; } @@ -20,7 +23,13 @@ public SealedBox(String publicKey, Encoder encoder) { this(encoder.decode(publicKey)); } - public SealedBox(byte[] publicKey, byte[] privateKey) { + public SealedBox(byte[] publicKey, byte[] privateKey) throws IllegalArgumentException { + if (publicKey == null) { + throw new IllegalArgumentException("Public key must not be null"); + } + if (privateKey == null) { + throw new IllegalArgumentException("Private key must not be null"); + } this.publicKey = publicKey; this.privateKey = privateKey; } @@ -30,8 +39,6 @@ public SealedBox(String publicKey, String privateKey, Encoder encoder) { } public byte[] encrypt(byte[] message) { - if (publicKey == null) - throw new RuntimeException("Encryption failed. Public key not available."); byte[] ct = new byte[message.length + SEAL_BYTES]; isValid(sodium().crypto_box_seal( ct, message, message.length, publicKey), @@ -40,9 +47,6 @@ public byte[] encrypt(byte[] message) { } public byte[] decrypt(byte[] ciphertext) { - if (privateKey == null) - throw new RuntimeException("Decryption failed. Private key not available."); - byte[] message = new byte[ciphertext.length - SEAL_BYTES]; isValid(sodium().crypto_box_seal_open( message, ciphertext, ciphertext.length, publicKey, privateKey), From 970d0098050eee1c8dbbbb839cabf6114ec05411 Mon Sep 17 00:00:00 2001 From: Omer Akram Date: Sat, 23 Mar 2019 01:25:10 +0500 Subject: [PATCH 4/6] No need to add unchecked exception to the signature --- src/main/java/org/libsodium/jni/crypto/SealedBox.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/libsodium/jni/crypto/SealedBox.java b/src/main/java/org/libsodium/jni/crypto/SealedBox.java index ea6812f..3d14bd7 100644 --- a/src/main/java/org/libsodium/jni/crypto/SealedBox.java +++ b/src/main/java/org/libsodium/jni/crypto/SealedBox.java @@ -11,7 +11,7 @@ public class SealedBox { private byte[] publicKey; private byte[] privateKey; - public SealedBox(byte[] publicKey) throws IllegalArgumentException { + public SealedBox(byte[] publicKey) { if (publicKey == null) { throw new IllegalArgumentException("Public key must not be null"); } @@ -23,7 +23,7 @@ public SealedBox(String publicKey, Encoder encoder) { this(encoder.decode(publicKey)); } - public SealedBox(byte[] publicKey, byte[] privateKey) throws IllegalArgumentException { + public SealedBox(byte[] publicKey, byte[] privateKey) { if (publicKey == null) { throw new IllegalArgumentException("Public key must not be null"); } From b999518e42a1802636dee86a919e13dbd3b03928 Mon Sep 17 00:00:00 2001 From: Omer Akram Date: Sat, 27 Apr 2019 23:20:55 +0500 Subject: [PATCH 5/6] Make decrypt a static method --- .../org/libsodium/jni/crypto/SealedBox.java | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/libsodium/jni/crypto/SealedBox.java b/src/main/java/org/libsodium/jni/crypto/SealedBox.java index 3d14bd7..01ef561 100644 --- a/src/main/java/org/libsodium/jni/crypto/SealedBox.java +++ b/src/main/java/org/libsodium/jni/crypto/SealedBox.java @@ -1,56 +1,51 @@ package org.libsodium.jni.crypto; import org.libsodium.jni.encoders.Encoder; +import org.libsodium.jni.keys.KeyPair; import static org.libsodium.jni.NaCl.sodium; import static org.libsodium.jni.SodiumConstants.SEAL_BYTES; -import static org.libsodium.jni.crypto.Util.isValid; public class SealedBox { - private byte[] publicKey; - private byte[] privateKey; + private byte[] mPublicKey; public SealedBox(byte[] publicKey) { if (publicKey == null) { throw new IllegalArgumentException("Public key must not be null"); } - this.publicKey = publicKey; - this.privateKey = null; + mPublicKey = publicKey; } public SealedBox(String publicKey, Encoder encoder) { this(encoder.decode(publicKey)); } - public SealedBox(byte[] publicKey, byte[] privateKey) { - if (publicKey == null) { - throw new IllegalArgumentException("Public key must not be null"); + private static boolean isValid(int status, String message) { + if (status != 0) { + throw new IllegalArgumentException(message); } - if (privateKey == null) { - throw new IllegalArgumentException("Private key must not be null"); - } - this.publicKey = publicKey; - this.privateKey = privateKey; - } - - public SealedBox(String publicKey, String privateKey, Encoder encoder) { - this(encoder.decode(publicKey), encoder.decode(privateKey)); + return true; } public byte[] encrypt(byte[] message) { byte[] ct = new byte[message.length + SEAL_BYTES]; isValid(sodium().crypto_box_seal( - ct, message, message.length, publicKey), + ct, message, message.length, mPublicKey), "Encryption failed"); return ct; } - public byte[] decrypt(byte[] ciphertext) { + public static byte[] decrypt(byte[] ciphertext, byte[] pubicKey, byte[] privateKey) { byte[] message = new byte[ciphertext.length - SEAL_BYTES]; isValid(sodium().crypto_box_seal_open( - message, ciphertext, ciphertext.length, publicKey, privateKey), + message, ciphertext, ciphertext.length, pubicKey, privateKey), "Decryption failed. Ciphertext failed verification"); return message; } + + public static byte[] decrypt(byte[] ciphertext, KeyPair keyPair) { + return decrypt(ciphertext, keyPair.getPublicKey().toBytes(), + keyPair.getPrivateKey().toBytes()); + } } From cd6e07ecb3676d674d595ff27813686f819f0c66 Mon Sep 17 00:00:00 2001 From: Omer Akram Date: Sat, 27 Apr 2019 23:28:47 +0500 Subject: [PATCH 6/6] Better error messaging --- .../org/libsodium/jni/crypto/SealedBox.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/libsodium/jni/crypto/SealedBox.java b/src/main/java/org/libsodium/jni/crypto/SealedBox.java index 01ef561..b218d29 100644 --- a/src/main/java/org/libsodium/jni/crypto/SealedBox.java +++ b/src/main/java/org/libsodium/jni/crypto/SealedBox.java @@ -21,26 +21,21 @@ public SealedBox(String publicKey, Encoder encoder) { this(encoder.decode(publicKey)); } - private static boolean isValid(int status, String message) { - if (status != 0) { - throw new IllegalArgumentException(message); - } - return true; - } - public byte[] encrypt(byte[] message) { byte[] ct = new byte[message.length + SEAL_BYTES]; - isValid(sodium().crypto_box_seal( - ct, message, message.length, mPublicKey), - "Encryption failed"); + if (sodium().crypto_box_seal(ct, message, message.length, mPublicKey) != 0) { + throw new IllegalArgumentException("Failed to encrypt"); + } return ct; } public static byte[] decrypt(byte[] ciphertext, byte[] pubicKey, byte[] privateKey) { byte[] message = new byte[ciphertext.length - SEAL_BYTES]; - isValid(sodium().crypto_box_seal_open( - message, ciphertext, ciphertext.length, pubicKey, privateKey), - "Decryption failed. Ciphertext failed verification"); + if (sodium().crypto_box_seal_open( + message, ciphertext, ciphertext.length, pubicKey, privateKey) != 0) { + throw new IllegalArgumentException( + "Failed to decrypt, ensure to provide the correct combination of parameters"); + } return message; }