package peergos.shared.crypto.asymmetric.curve25519; import peergos.shared.cbor.*; import peergos.shared.crypto.TweetNaCl; import peergos.shared.crypto.asymmetric.PublicBoxingKey; import peergos.shared.crypto.asymmetric.SecretBoxingKey; import peergos.shared.crypto.random.*; import peergos.shared.util.ArrayOps; import java.io.DataOutput; import java.io.IOException; import java.util.*; public class Curve25519PublicKey implements PublicBoxingKey { private final byte[] publicKey; private final Curve25519 implementation; private final SafeRandom random; public Curve25519PublicKey(byte[] publicKey, Curve25519 provider, SafeRandom random) { if (publicKey.length != 32) throw new IllegalArgumentException("Incorrect curve25519 public key length! " + publicKey.length); this.publicKey = publicKey; this.implementation = provider; this.random = random; } public PublicBoxingKey.Type type() { return Type.Curve25519; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Curve25519PublicKey that = (Curve25519PublicKey) o; return Arrays.equals(publicKey, that.publicKey); } @Override public int hashCode() { return Arrays.hashCode(publicKey); } public byte[] getPublicBoxingKey() { return Arrays.copyOfRange(publicKey, 0, publicKey.length); } public byte[] encryptMessageFor(byte[] input, SecretBoxingKey from) { byte[] nonce = createNonce(); return ArrayOps.concat(implementation.crypto_box(input, nonce, publicKey, from.getSecretBoxingKey()), nonce); } public byte[] createNonce() { byte[] nonce = new byte[TweetNaCl.BOX_NONCE_BYTES]; random.randombytes(nonce, 0, nonce.length); return nonce; } @Override public CborObject toCbor() { return new CborObject.CborList(Arrays.asList(new CborObject.CborLong(type().value), new CborObject.CborByteArray(publicKey))); } public static Curve25519PublicKey fromCbor(CborObject cbor, Curve25519 provider, SafeRandom random) { if (! (cbor instanceof CborObject.CborList)) throw new IllegalStateException("Invalid cbor for PublicBoxingKey! " + cbor); CborObject.CborByteArray key = (CborObject.CborByteArray) ((CborObject.CborList) cbor).value.get(1); return new Curve25519PublicKey(key.value, provider, random); } }