Skip to content

Commit

Permalink
Combine message sealing classes
Browse files Browse the repository at this point in the history
  • Loading branch information
jvz committed Dec 7, 2020
1 parent 2e41f8e commit 8e24013
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 64 deletions.
18 changes: 9 additions & 9 deletions java15/src/test/java/dev/o1c/SecretKeySealTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@
class SecretKeySealTest {

private Random random;
private Sealer sealer;
private SecureData.Seal seal;

@BeforeEach
void setUp() {
var key = SealedData.generateKey();
sealer = SealedData.usingKey(key);
var key = SecureData.generateKey();
seal = SecureData.usingKey(key);
random = new Random(ByteBuffer.wrap(key.getEncoded()).getLong());
}

@Test
void sealNoContext() {
var plaintext = new byte[4096];
random.nextBytes(plaintext);
assertArrayEquals(plaintext, sealer.unseal(sealer.seal(plaintext)));
assertArrayEquals(plaintext, seal.unseal(seal.seal(plaintext)));
}

@Test
Expand All @@ -49,15 +49,15 @@ void sealWithContext() {
random.nextBytes(plaintext);
var context = new byte[42];
random.nextBytes(context);
assertArrayEquals(plaintext, sealer.unseal(sealer.seal(plaintext, context), context));
assertArrayEquals(plaintext, seal.unseal(seal.seal(plaintext, context), context));
}

@Test
void tokenSealNoContext() {
var plaintext = new byte[2043];
random.nextBytes(plaintext);
var secureData = sealer.tokenSeal(plaintext);
assertArrayEquals(plaintext, sealer.tokenUnseal(secureData.getEncryptedData(), secureData.getToken()));
var secureData = seal.tokenSeal(plaintext);
assertArrayEquals(plaintext, seal.tokenUnseal(secureData.getEncryptedData(), secureData.getToken()));
}

@Test
Expand All @@ -66,7 +66,7 @@ void tokenSealWithContext() {
random.nextBytes(plaintext);
var context = new byte[63];
random.nextBytes(context);
var secureData = sealer.tokenSeal(plaintext, context);
assertArrayEquals(plaintext, sealer.tokenUnseal(secureData.getEncryptedData(), secureData.getToken(), context));
var secureData = seal.tokenSeal(plaintext, context);
assertArrayEquals(plaintext, seal.tokenUnseal(secureData.getEncryptedData(), secureData.getToken(), context));
}
}
43 changes: 0 additions & 43 deletions java8/src/main/java/dev/o1c/Sealer.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.security.SecureRandom;
import java.util.Objects;

class SecretKeySealer implements Sealer {
class SecretKeySeal implements SecureData.Seal {
private static final int TAG_SIZE = 16;
private static final int NONCE_SIZE = 12;
private static final int SEAL_TYPE = 0x43433230; // CC20 in ASCII, big endian order
Expand All @@ -44,7 +44,7 @@ class SecretKeySealer implements Sealer {

private final SecretKey key;

SecretKeySealer(SecretKey key) {
SecretKeySeal(SecretKey key) {
this.key = key;
}

Expand All @@ -68,11 +68,11 @@ public byte[] seal(byte[] data, byte[] context) {
@Override
public byte[] unseal(byte[] sealedData, byte[] context) {
Objects.requireNonNull(sealedData);
int sealType = ByteOps.unpackInt(sealedData, 0);
int sealType = ByteOps.unpackIntBE(sealedData, 0);
if (sealType != SEAL_TYPE) {
throw new InvalidSealException("Unsupported seal type detected: " + Integer.toHexString(sealType));
}
int dataLength = ByteOps.unpackInt(sealedData, Integer.BYTES) + TAG_SIZE;
int dataLength = ByteOps.unpackIntBE(sealedData, Integer.BYTES) + TAG_SIZE;
int nonceOffset = Integer.BYTES * 2;
IvParameterSpec nonce = new IvParameterSpec(sealedData, nonceOffset, NONCE_SIZE);
int dataOffset = nonceOffset + NONCE_SIZE;
Expand All @@ -84,7 +84,7 @@ public byte[] unseal(byte[] sealedData, byte[] context) {
}

@Override
public SealedData tokenSeal(byte[] data, byte[] context) {
public SecureData tokenSeal(byte[] data, byte[] context) {
Objects.requireNonNull(data);
Cipher cipher = initEncrypt(context);
byte[] nonce = cipher.getIV();
Expand All @@ -101,7 +101,7 @@ public SealedData tokenSeal(byte[] data, byte[] context) {
token.put(ciphertext);
token.put(nonce);
token.putInt(SEAL_TYPE);
return new SealedData(encryptedData, token.array());
return new SecureData(encryptedData, token.array());
}

@Override
Expand All @@ -111,7 +111,7 @@ public byte[] tokenUnseal(byte[] encryptedData, byte[] token, byte[] context) {
if (token.length != TOKEN_SIZE) {
throw new InvalidSealException("Token size must be " + TOKEN_SIZE + " bytes");
}
int tokenType = ByteOps.unpackInt(token, TAG_SIZE + NONCE_SIZE);
int tokenType = ByteOps.unpackIntBE(token, TAG_SIZE + NONCE_SIZE);
if (tokenType != SEAL_TYPE) {
throw new InvalidSealException("Unsupported seal token type detected: " + Integer.toHexString(tokenType));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import javax.crypto.SecretKey;
import java.util.Objects;

public final class SealedData {
public final class SecureData {
private final byte[] encryptedData;
private final byte[] token;

public SealedData(byte[] encryptedData, byte[] token) {
public SecureData(byte[] encryptedData, byte[] token) {
this.encryptedData = Objects.requireNonNull(encryptedData);
this.token = Objects.requireNonNull(token);
}
Expand All @@ -42,7 +42,33 @@ public static SecretKey generateKey() {
return KeyGenerator.getInstance().generateKey();
}

public static Sealer usingKey(SecretKey key) {
return new SecretKeySealer(Objects.requireNonNull(key));
public static Seal usingKey(SecretKey key) {
return new SecretKeySeal(Objects.requireNonNull(key));
}

public interface Seal {
byte[] seal(byte[] data, byte[] context);

default byte[] seal(byte[] data) {
return seal(data, null);
}

byte[] unseal(byte[] sealedData, byte[] context);

default byte[] unseal(byte[] sealedData) {
return unseal(sealedData, null);
}

SecureData tokenSeal(byte[] data, byte[] context);

default SecureData tokenSeal(byte[] data) {
return tokenSeal(data, null);
}

byte[] tokenUnseal(byte[] encryptedData, byte[] token, byte[] context);

default byte[] tokenUnseal(byte[] encryptedData, byte[] token) {
return tokenUnseal(encryptedData, token, null);
}
}
}
31 changes: 30 additions & 1 deletion java8/src/main/java/dev/o1c/spi/ByteOps.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,39 @@ public static byte[] reverseCopyOf(byte[] buf) {
return copy;
}

public static int unpackInt(byte[] buf, int off) {
public static int unpackIntBE(byte[] buf, int off) {
return (buf[off] & 0xff) << 24 | (buf[off + 1] & 0xff) << 16 | (buf[off + 2] & 0xff) << 8 | buf[off + 3] & 0xff;
}

public static int unpackIntLE(byte[] buf, int off) {
return buf[off] & 0xff | (buf[off + 1] & 0xff) << 8 | (buf[off + 2] & 0xff) << 16 | (buf[off + 3] & 0xff) << 24;
}

public static void unpackIntsLE(byte[] buf, int off, int nrInts, int[] dst, int dstOff) {
for (int i = 0; i < nrInts; i++) {
dst[dstOff + i] = unpackIntLE(buf, off + i * 4);
}
}

public static int[] unpackIntsLE(byte[] buf, int off, int nrInts) {
int[] values = new int[nrInts];
unpackIntsLE(buf, off, nrInts, values, 0);
return values;
}

public static void packIntLE(int value, byte[] dst, int off) {
dst[off] = (byte) value;
dst[off + 1] = (byte) (value >>> 8);
dst[off + 2] = (byte) (value >>> 16);
dst[off + 3] = (byte) (value >>> 24);
}

public static void packIntsLE(int[] values, int off, int nrInts, byte[] dst, int dstOff) {
for (int i = 0; i < nrInts; i++) {
packIntLE(values[off + i], dst, dstOff + i * 4);
}
}

public static byte[] fromHex(CharSequence data) {
return HEX_DECODER.decode(data);
}
Expand Down

0 comments on commit 8e24013

Please sign in to comment.