Skip to content

Commit

Permalink
Merge pull request #53 from serac/52-safe-header
Browse files Browse the repository at this point in the history
Define new ciphertext header format.
  • Loading branch information
dfish3r authored Jan 29, 2020
2 parents fafccd0 + 00395c2 commit 311baf1
Show file tree
Hide file tree
Showing 10 changed files with 708 additions and 74 deletions.
65 changes: 52 additions & 13 deletions src/main/java/org/cryptacular/CiphertextHeader.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@
* decrypt outstanding data which will be subsequently re-encrypted with a new key.</p>
*
* @author Middleware Services
*
* @deprecated Superseded by {@link CiphertextHeaderV2}
*/
@Deprecated
public class CiphertextHeader
{
/** Maximum nonce length in bytes. */
protected static final int MAX_NONCE_LEN = 255;

/** Maximum key name length in bytes. */
protected static final int MAX_KEYNAME_LEN = 500;

/** Header nonce field value. */
private final byte[] nonce;
protected final byte[] nonce;

/** Header key name field value. */
private String keyName;
protected final String keyName;

/** Header length in bytes. */
private int length;
protected final int length;


/**
Expand All @@ -67,12 +75,17 @@ public CiphertextHeader(final byte[] nonce)
*/
public CiphertextHeader(final byte[] nonce, final String keyName)
{
this.nonce = nonce;
this.length = 8 + nonce.length;
if (nonce.length > MAX_NONCE_LEN) {
throw new IllegalArgumentException("Nonce exceeds size limit in bytes (" + MAX_NONCE_LEN + ")");
}
if (keyName != null) {
this.length += 4 + keyName.getBytes().length;
this.keyName = keyName;
if (ByteUtil.toBytes(keyName).length > MAX_KEYNAME_LEN) {
throw new IllegalArgumentException("Key name exceeds size limit in bytes (" + MAX_KEYNAME_LEN + ")");
}
}
this.nonce = nonce;
this.keyName = keyName;
length = computeLength();
}

/**
Expand Down Expand Up @@ -127,6 +140,19 @@ public byte[] encode()
}


/**
* @return Length of this header encoded as bytes.
*/
protected int computeLength()
{
int len = 8 + nonce.length;
if (keyName != null) {
len += 4 + keyName.getBytes().length;
}
return len;
}


/**
* Creates a header from encrypted data containing a cleartext header prepended to the start.
*
Expand All @@ -143,17 +169,20 @@ public static CiphertextHeader decode(final byte[] data) throws EncodingExceptio

final int length = bb.getInt();
if (length < 0) {
throw new EncodingException("Invalid ciphertext header length: " + length);
throw new EncodingException("Bad ciphertext header");
}

final byte[] nonce;
int nonceLen = 0;
try {
nonceLen = bb.getInt();
if (nonceLen > MAX_NONCE_LEN) {
throw new EncodingException("Bad ciphertext header: maximum nonce length exceeded");
}
nonce = new byte[nonceLen];
bb.get(nonce);
} catch (IndexOutOfBoundsException | BufferUnderflowException e) {
throw new EncodingException("Invalid nonce length: " + nonceLen);
throw new EncodingException("Bad ciphertext header");
}

String keyName = null;
Expand All @@ -162,11 +191,14 @@ public static CiphertextHeader decode(final byte[] data) throws EncodingExceptio
int keyLen = 0;
try {
keyLen = bb.getInt();
if (keyLen > MAX_KEYNAME_LEN) {
throw new EncodingException("Bad ciphertext header: maximum key length exceeded");
}
b = new byte[keyLen];
bb.get(b);
keyName = new String(b);
} catch (IndexOutOfBoundsException | BufferUnderflowException e) {
throw new EncodingException("Invalid key length: " + keyLen);
throw new EncodingException("Bad ciphertext header");
}
}

Expand All @@ -188,17 +220,20 @@ public static CiphertextHeader decode(final InputStream input) throws EncodingEx
{
final int length = ByteUtil.readInt(input);
if (length < 0) {
throw new EncodingException("Invalid ciphertext header length: " + length);
throw new EncodingException("Bad ciphertext header");
}

final byte[] nonce;
int nonceLen = 0;
try {
nonceLen = ByteUtil.readInt(input);
if (nonceLen > MAX_NONCE_LEN) {
throw new EncodingException("Bad ciphertext header: maximum nonce size exceeded");
}
nonce = new byte[nonceLen];
input.read(nonce);
} catch (ArrayIndexOutOfBoundsException e) {
throw new EncodingException("Invalid nonce length: " + nonceLen);
throw new EncodingException("Bad ciphertext header");
} catch (IOException e) {
throw new StreamException(e);
}
Expand All @@ -209,10 +244,13 @@ public static CiphertextHeader decode(final InputStream input) throws EncodingEx
int keyLen = 0;
try {
keyLen = ByteUtil.readInt(input);
if (keyLen > MAX_KEYNAME_LEN) {
throw new EncodingException("Bad ciphertext header: maximum key length exceeded");
}
b = new byte[keyLen];
input.read(b);
} catch (ArrayIndexOutOfBoundsException e) {
throw new EncodingException("Invalid key length: " + keyLen);
throw new EncodingException("Bad ciphertext header");
} catch (IOException e) {
throw new StreamException(e);
}
Expand All @@ -221,4 +259,5 @@ public static CiphertextHeader decode(final InputStream input) throws EncodingEx

return new CiphertextHeader(nonce, keyName);
}

}
Loading

0 comments on commit 311baf1

Please sign in to comment.