Skip to content

Commit

Permalink
Settle on/be clearer and more consistent about not-thread-safety
Browse files Browse the repository at this point in the history
  • Loading branch information
jchambers committed Mar 3, 2024
1 parent d21a726 commit b1af66e
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 41 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/eatthepath/noise/NoiseHandshake.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
* type (i.e. one-way or interactive) and pass Noise transport messages between the initiator and responder as
* needed.</p>
*
* <p>Noise handshake instances are stateful and are <em>not</em> thread-safe.</p>
*
* <h2>Interactive patterns</h2>
*
* <p>In the most common case, Noise handshakes implement a interactive pattern in which both parties will send and
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/eatthepath/noise/NoiseTransport.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.eatthepath.noise;

/**
* A Noise transport is an interactive reader and writer of Noise transport messages. In the terminology of the Noise
* <p>A Noise transport is an interactive reader and writer of Noise transport messages. In the terminology of the Noise
* Protocol Framework specification, a {@code NoiseTransport} instance encapsulates the two "cipher states" produced by
* "splitting" a {@link NoiseHandshake}.
* "splitting" a {@link NoiseHandshake}.</p>
*
* <p>Noise transport instances are stateful and are <em>not</em> thread-safe.</p>
*
* @see NoiseHandshake#toTransport()
*/
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/eatthepath/noise/NoiseTransportReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import java.nio.ByteBuffer;

/**
* A Noise transport reader decrypts Noise transport messages. In the terminology of the Noise
* <p>A Noise transport reader decrypts Noise transport messages. In the terminology of the Noise
* Protocol Framework specification, a {@code NoiseTransportReader} instance encapsulates a "cipher state" produced by
* "splitting" a {@link NoiseHandshake} instance.
* "splitting" a {@link NoiseHandshake} instance.</p>
*
* <p>Noise transport reader instances are stateful and are <em>not</em> thread-safe.</p>
*
* @see NoiseHandshake#toTransportReader()
* @see NoiseHandshake#toTransport()
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/eatthepath/noise/NoiseTransportWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import java.nio.ByteBuffer;

/**
* A Noise transport writer encrypts Noise transport messages. In the terminology of the Noise Protocol Framework
* <p>A Noise transport writer encrypts Noise transport messages. In the terminology of the Noise Protocol Framework
* specification, a {@code NoiseTransportWriter} instance encapsulates a "cipher state" produced by "splitting" a
* {@link NoiseHandshake} instance.
* {@link NoiseHandshake} instance.</p>
*
* <p>Noise transport writer instances are stateful and are <em>not</em> thread-safe.</p>
*
* @see NoiseHandshake#toTransportWriter()
* @see NoiseHandshake#toTransport()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
package com.eatthepath.noise.component;

import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.crypto.*;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;

@ThreadSafe
abstract class AbstractNoiseCipher implements NoiseCipher {

private final Cipher cipher;

AbstractNoiseCipher(final Cipher cipher) {
this.cipher = cipher;
}

@FunctionalInterface
private interface CipherFinalizer<T> {
T doFinal() throws IllegalBlockSizeException, BadPaddingException, ShortBufferException;
}

protected abstract Cipher getCipher();

protected abstract AlgorithmParameterSpec getAlgorithmParameters(final long nonce);

@Override
Expand All @@ -28,8 +30,6 @@ public int encrypt(final Key key,
final ByteBuffer plaintext,
final ByteBuffer ciphertext) throws ShortBufferException {

final Cipher cipher = getCipher();

initCipher(cipher, Cipher.ENCRYPT_MODE, key, nonce);

if (associatedData != null) {
Expand All @@ -54,8 +54,6 @@ public int encrypt(final Key key,
final byte[] ciphertext,
final int ciphertextOffset) throws ShortBufferException {

final Cipher cipher = getCipher();

initCipher(cipher, Cipher.ENCRYPT_MODE, key, nonce);

if (associatedData != null) {
Expand All @@ -73,8 +71,6 @@ public int decrypt(final Key key,
final ByteBuffer ciphertext,
final ByteBuffer plaintext) throws AEADBadTagException, ShortBufferException {

final Cipher cipher = getCipher();

initCipher(cipher, Cipher.DECRYPT_MODE, key, nonce);

if (associatedData != null) {
Expand All @@ -99,8 +95,6 @@ public int decrypt(final Key key,
final byte[] plaintext,
final int plaintextOffset) throws AEADBadTagException, ShortBufferException {

final Cipher cipher = getCipher();

initCipher(cipher, Cipher.DECRYPT_MODE, key, nonce);

if (associatedData != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.eatthepath.noise.component;

import javax.annotation.concurrent.ThreadSafe;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
Expand All @@ -10,11 +9,13 @@
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

@ThreadSafe
class AesGcmCipher extends AbstractNoiseCipher {

@Override
protected Cipher getCipher() {
AesGcmCipher() {
super(getCipher());
}

private static Cipher getCipher() {
try {
return Cipher.getInstance("AES/GCM/NoPadding");
} catch (final NoSuchAlgorithmException | NoSuchPaddingException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.eatthepath.noise.component;

import javax.annotation.concurrent.ThreadSafe;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
Expand All @@ -11,23 +10,15 @@
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

@ThreadSafe
class ChaCha20Poly1305Cipher extends AbstractNoiseCipher {

private static final String ALGORITHM = "ChaCha20-Poly1305";

public ChaCha20Poly1305Cipher() throws NoSuchAlgorithmException {
// Make sure that we can instantiate a cipher and fail fast if not
try {
Cipher.getInstance(ALGORITHM);
} catch (final NoSuchPaddingException e) {
// This should never happen since we're not specifying a padding
throw new AssertionError("Padding not supported, but no padding specified", e);
}
super(getCipher());
}

@Override
protected Cipher getCipher() {
private static Cipher getCipher() {
try {
return Cipher.getInstance(ALGORITHM);
} catch (final NoSuchPaddingException e) {
Expand Down
11 changes: 3 additions & 8 deletions src/main/java/com/eatthepath/noise/component/NoiseCipher.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package com.eatthepath.noise.component;

import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.crypto.AEADBadTagException;
import javax.crypto.ShortBufferException;
import java.nio.ByteBuffer;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

/**
* <p>A Noise cipher is a stateless object that encrypts and decrypts data for use in a Noise protocol. Noise cipher
* implementations must be thread-safe (i.e. calling encryption/decryption methods on different sets of data
* concurrently and from different threads must have no adverse effect).</p>
*
* <p>Noise cipher implementations must operate in AEAD mode, produce a 16-byte AEAD tag when encrypting data, and
* verify a 16-byte AEAD tag when decrypting data.</p>
* A Noise cipher is a stateless object that encrypts and decrypts data for use in a Noise protocol. Noise cipher
* implementations must operate in AEAD mode, produce a 16-byte AEAD tag when encrypting data, and verify a 16-byte
* AEAD tag when decrypting data.
*/
@ThreadSafe
public interface NoiseCipher {

/**
Expand Down

0 comments on commit b1af66e

Please sign in to comment.