package peergos.shared.crypto.symmetric;
import peergos.shared.cbor.*;
import peergos.shared.crypto.*;
import peergos.shared.crypto.random.*;
import java.util.*;
public class TweetNaClKey implements SymmetricKey
{
public static final int KEY_BYTES = 32;
public static final int NONCE_BYTES = 24;
private final byte[] secretKey;
private final boolean isDirty;
private final Salsa20Poly1305 implementation;
private final SafeRandom random;
public TweetNaClKey(byte[] secretKey, boolean isDirty, Salsa20Poly1305 implementation, SafeRandom random)
{
if (secretKey.length != TweetNaCl.SECRETBOX_KEY_BYTES)
throw new IllegalStateException("Incorrect key size! ("+secretKey.length+")");
this.secretKey = secretKey;
this.isDirty = isDirty;
this.implementation = implementation;
this.random = random;
}
public Type type() {
return Type.TweetNaCl;
}
public byte[] getKey()
{
return secretKey;
}
public boolean isDirty() {
return isDirty;
}
public SymmetricKey makeDirty() {
return new TweetNaClKey(secretKey, true, implementation, random);
}
public byte[] encrypt(byte[] data, byte[] nonce)
{
return encrypt(secretKey, data, nonce, implementation);
}
public byte[] decrypt(byte[] data, byte[] nonce)
{
return decrypt(secretKey, data, nonce, implementation);
}
public static byte[] encrypt(byte[] key, byte[] data, byte[] nonce, Salsa20Poly1305 implementation)
{
return implementation.secretbox(data, nonce, key);
}
public static byte[] decrypt(byte[] key, byte[] cipher, byte[] nonce, Salsa20Poly1305 implementation)
{
return implementation.secretbox_open(cipher, nonce, key);
}
public byte[] createNonce()
{
byte[] res = new byte[NONCE_BYTES];
random.randombytes(res, 0, res.length);
return res;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TweetNaClKey that = (TweetNaClKey) o;
if (isDirty != that.isDirty) return false;
return Arrays.equals(secretKey, that.secretKey);
}
@Override
public int hashCode() {
int result = Arrays.hashCode(secretKey);
result = 31 * result + (isDirty ? 1 : 0);
return result;
}
public CborObject toCbor() {
return new CborObject.CborList(Arrays.asList(
new CborObject.CborLong(type().value),
new CborObject.CborByteArray(secretKey),
new CborObject.CborBoolean(isDirty)));
}
public static TweetNaClKey fromCbor(CborObject cbor, Salsa20Poly1305 provider, SafeRandom random) {
if (! (cbor instanceof CborObject.CborList))
throw new IllegalStateException("Invalid cbor for PublicBoxingKey! " + cbor);
CborObject.CborByteArray secretKey = (CborObject.CborByteArray) ((CborObject.CborList) cbor).value.get(1);
CborObject.CborBoolean isDirty = (CborObject.CborBoolean) ((CborObject.CborList) cbor).value.get(2);
return new TweetNaClKey(secretKey.value, isDirty.value, provider, random);
}
public static TweetNaClKey random(Salsa20Poly1305 provider, SafeRandom random)
{
byte[] key = new byte[KEY_BYTES];
random.randombytes(key, 0, KEY_BYTES);
return new TweetNaClKey(key, false, provider, random);
}
}