Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SealedBox support #127

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Conversation

om26er
Copy link

@om26er om26er commented Mar 13, 2019

Code is mostly taken from https://github.com/abstractj/kalium/blob/master/src/main/java/org/abstractj/kalium/crypto/SealedBox.java, also doesn't currently have tests and is mostly untested.

I assume we would want to change the method signatures to throw exceptions before merging.

}

public byte[] encrypt(byte[] message) {
if (publicKey == null)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to avoid waiting until encrypt time to determine that the public key passed at initialization is incorrect.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, moved that check into the constructor, now throwing IllegalArgumentException though that also inherits RuntimeException. Couldn't think of an appropriate checked exception here (if we want to go that way, we could do a custom exception though).

}

public byte[] decrypt(byte[] ciphertext) {
if (privateKey == null)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to avoid waiting until decrypt time to determine that the public key passed at initialization is incorrect.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed that as well.

@oberstet
Copy link

great to see support for SealedBox is coming (we will use it to add XBR support to AutobahnJava, a WebSocket/WAMP library). quick comments:

  • regarding constructors: the sender side only needs the public key of the receiver, and the receiver only needs its own private key - from which the public key is derived. so the constructors could be "cleaned up" based on this (eg look at https://pynacl.readthedocs.io/en/stable/public/#nacl-public-sealedbox) - having said that, I don't know about the interface rules/design libsodium-jni follow, and we can certainly use the current ctors
  • rgd test coverage: here is how pynacl treats that: https://pynacl.readthedocs.io/en/stable/vectors/sealedbox_vectors/ - they use a C based tool to generate test vector. since this library is wrapping the underlying libsodium, I don't think it is super important (testing the underlying libsodium is obviously done in upstream) .. the bugs that could creep in in the wrapping code here are more about actually calling the right libsodium stuff and not messing up this calling and forwarding of parameters/data from java to libsodium (C), so I do think tests at a higher level (as in, using this library) would make more sense - if so.

@om26er om26er changed the title [WIP] Add preliminary SealedBox support Add SealedBox support Mar 27, 2019
@oberstet
Copy link

oberstet commented Apr 2, 2019

@om26er ok, I forked this to our org at https://github.com/crossbario/libsodium-jni - could you pls continue there and merge above - we need to continue work and are blocked on this, so lets use our fork from now on

@joshjdevl
Copy link
Owner

I'm sorry, though I don't see how this matches the libsodium api for sealed box.

The proposed constructor is expecting the keys to be generated outside the constructor. Why are the keys being generated outside the constructor? What is the use case?


public byte[] encrypt(byte[] message) {
byte[] ct = new byte[message.length + SEAL_BYTES];
isValid(sodium().crypto_box_seal(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Util class is marked deprecated and should not be used.

isValid is supposed to return a boolean, though throws a RuntimeException.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I have removed the usage of isValid and have moved the check internally.

What's the planned approach to deal with all the deprecated classes ?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Planning to remove the deprecated classes in a major release.
The deprecated classes haven't been removed yet as it's unclear impact to downstream developers.

@oberstet
Copy link

I agree with @joshjdevl the ephemeral key should not be a constructor parameter (provided externally), but IMO should be created newly each time encrypt is called, so that a single SealedBox object can be (safely) reused for multiple encrypt operations using the same recipient public key.

fwiw, pynacl has this API: https://pynacl.readthedocs.io/en/stable/public/#nacl-public-sealedbox

@om26er
Copy link
Author

om26er commented Apr 27, 2019

I agree with @joshjdevl the ephemeral key should not be a constructor parameter (provided externally), but IMO should be created newly each time encrypt is called, so that a single SealedBox object can be (safely) reused for multiple encrypt operations using the same recipient public key.

Ok, it seems the private key was not needed to encrypt, as that was taken care by libsodium internally, it was used to actually decrypt the message, which didn't really make sense, so now I have changed the decrypt method to be a static, which takes ciphertext, publicKey and privateKey as parameters.

I think a similar approach could also be used for the encrypt method i.e. make that a static as well, which takes two parameters: message and publicKey.

@oberstet
Copy link

rgd deprecated classes: not sure what is meant here (what classes?). if sth is deprecated in the future, lets fix it then - unless the deprecated classes would be in the interface of this new class. my 2cts


my main remaining itch would be: IMO the decrypt interface is still slightly "wrong". It takes a private key as a parameter, while that should come from the ctor (stored in private member attribute).

as a sender, I want to create a sealed box using the receiver public key provided in ctor, and then reuse that box to encrypt many messages - this is now the case.

as a receiver, I want to create a sealed box using my private key provided in ctor, and then reuse that box to decrypt many messages - this is not yet the case (I have to store my private key outside, and then provide it each time I decrypt a message).

this interface design is asymmetric (rgd where pub/priv key is provided - once in ctor, once in method).

again, pynacl has got this right, in as: the interface is minimal and intuitive ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants