Skip to content

Commit

Permalink
Refactoring in crypto.hpke
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdettman committed Jan 21, 2025
1 parent 24797f6 commit 8b813e1
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 212 deletions.
107 changes: 37 additions & 70 deletions core/src/main/java/org/bouncycastle/crypto/hpke/AEAD.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Bytes;
import org.bouncycastle.util.Pack;

public class AEAD
{

private final short aeadId;
private final byte[] key;
private final byte[] baseNonce;
Expand All @@ -32,7 +32,7 @@ public AEAD(short aeadId, byte[] key, byte[] baseNonce)
{
case HPKE.aead_AES_GCM128:
case HPKE.aead_AES_GCM256:
cipher = new GCMBlockCipher(new AESEngine());
cipher = GCMBlockCipher.newInstance(AESEngine.newInstance());
break;
case HPKE.aead_CHACHA20_POLY1305:
cipher = new ChaCha20Poly1305();
Expand All @@ -42,106 +42,73 @@ public AEAD(short aeadId, byte[] key, byte[] baseNonce)
}
}

// used by Sender
public byte[] seal(byte[] aad, byte[] pt)
throws InvalidCipherTextException
{
return process(true, aad, pt, 0, pt.length);
}

// used by Sender
public byte[] seal(byte[] aad, byte[] pt, int ptOffset, int ptLength)
throws InvalidCipherTextException
{
if (ptOffset < 0 || ptOffset > pt.length)
{
throw new IndexOutOfBoundsException("Invalid offset");
}
if (ptOffset + ptLength > pt.length)
{
throw new IndexOutOfBoundsException("Invalid length");
}

CipherParameters params;
switch (aeadId)
{
case HPKE.aead_AES_GCM128:
case HPKE.aead_AES_GCM256:
case HPKE.aead_CHACHA20_POLY1305:
params = new ParametersWithIV(new KeyParameter(key), ComputeNonce());
break;
case HPKE.aead_EXPORT_ONLY:
default:
throw new IllegalStateException("Export only mode, cannot be used to seal/open");
}
cipher.init(true, params);
cipher.processAADBytes(aad, 0, aad.length);
byte[] ct = new byte[cipher.getOutputSize(ptLength)];
int len = cipher.processBytes(pt, ptOffset, ptLength, ct, 0);
cipher.doFinal(ct, len);
Arrays.validateSegment(pt, ptOffset, ptLength);

seq++;
return ct;
return process(true, aad, pt, ptOffset, ptLength);
}

// used by Sender
public byte[] seal(byte[] aad, byte[] pt)
// used by Receiver
public byte[] open(byte[] aad, byte[] ct)
throws InvalidCipherTextException
{
return this.seal(aad, pt, 0, pt.length);
return process(false, aad, ct, 0, ct.length);
}

// used by Receiver
public byte[] open(byte[] aad, byte[] ct, int ctOffset, int ctLength)
throws InvalidCipherTextException
{
if (ctOffset < 0 || ctOffset > ct.length)
{
throw new IndexOutOfBoundsException("Invalid offset");
}
if (ctOffset + ctLength > ct.length)
{
throw new IndexOutOfBoundsException("Invalid length");
}
Arrays.validateSegment(ct, ctOffset, ctLength);

return process(false, aad, ct, ctOffset, ctLength);
}

private byte[] computeNonce()
{
byte[] seq_bytes = Pack.longToBigEndian(seq++);
byte[] nonce = Arrays.clone(baseNonce);
Bytes.xorTo(8, seq_bytes, 0, nonce, nonce.length - 8);
return nonce;
}

private byte[] process(boolean forEncryption, byte[] aad, byte[] buf, int off, int len)
throws InvalidCipherTextException
{
CipherParameters params;
switch (aeadId)
{
case HPKE.aead_AES_GCM128:
case HPKE.aead_AES_GCM256:
case HPKE.aead_CHACHA20_POLY1305:
params = new ParametersWithIV(new KeyParameter(key), ComputeNonce());
params = new ParametersWithIV(new KeyParameter(key), computeNonce());
break;
case HPKE.aead_EXPORT_ONLY:
default:
throw new IllegalStateException("Export only mode, cannot be used to seal/open");
}

cipher.init(false, params);
cipher.init(forEncryption, params);
cipher.processAADBytes(aad, 0, aad.length);

byte[] pt = new byte[cipher.getOutputSize(ctLength)];
int len = cipher.processBytes(ct, ctOffset, ctLength, pt, 0);
len += cipher.doFinal(pt, len);

seq++;
return pt;
}

// used by Receiver
public byte[] open(byte[] aad, byte[] ct)
throws InvalidCipherTextException
{
return this.open(aad, ct, 0, ct.length);
}

private byte[] ComputeNonce()
{
byte[] seq_bytes = Pack.longToBigEndian(seq);
int Nn = baseNonce.length;
byte[] nonce = Arrays.clone(baseNonce);
//xor
for (int i = 0; i < 8; i++)
byte[] output = new byte[cipher.getOutputSize(len)];
int pos = cipher.processBytes(buf, off, len, output, 0);
pos += cipher.doFinal(output, pos);
if (pos != output.length)
{
nonce[Nn - 8 + i] ^= seq_bytes[i];
// Existing AEAD modes should return exact value for getOutputSize.
throw new IllegalStateException();
}
return nonce;
return output;
}


}

Loading

0 comments on commit 8b813e1

Please sign in to comment.