package im.actor.core.modules.encryption.entity; import java.io.IOException; import im.actor.core.api.ApiEncryptionKey; import im.actor.core.api.ApiEncryptionKeySignature; import im.actor.core.util.RandomUtils; import im.actor.runtime.Crypto; import im.actor.runtime.bser.BserObject; import im.actor.runtime.bser.BserValues; import im.actor.runtime.bser.BserWriter; import im.actor.runtime.crypto.Curve25519; import im.actor.runtime.crypto.Curve25519KeyPair; import im.actor.runtime.crypto.primitives.util.ByteStrings; import im.actor.runtime.crypto.ratchet.RatchetKeySignature; import im.actor.runtime.function.Function; import im.actor.runtime.function.Predicate; import im.actor.runtime.function.Supplier; public class PrivateKey extends BserObject { public static final Predicate<PrivateKey> PRE_KEY_EQUALS(final byte[] publicKey) { return new Predicate<PrivateKey>() { @Override public boolean apply(PrivateKey privateKey) { return ByteStrings.isEquals(publicKey, privateKey.getPublicKey()); } }; } public static final Predicate<PrivateKey> PRE_KEY_EQUALS_ID(final long id) { return new Predicate<PrivateKey>() { @Override public boolean apply(PrivateKey privateKey) { return privateKey.getKeyId() == id; } }; } public static final Function<PrivateKey, ApiEncryptionKey> TO_API = new Function<PrivateKey, ApiEncryptionKey>() { @Override public ApiEncryptionKey apply(PrivateKey privateKey) { return privateKey.toApiKey(); } }; public static final Function<PrivateKey, ApiEncryptionKeySignature> SIGN(final PrivateKey identity) { return new Function<PrivateKey, ApiEncryptionKeySignature>() { @Override public ApiEncryptionKeySignature apply(PrivateKey privateKey) { byte[] signature = Curve25519.calculateSignature(Crypto.randomBytes(64), identity.getKey(), RatchetKeySignature.hashForSignature(privateKey.getKeyId(), privateKey.getKeyAlg(), privateKey.getPublicKey())); return new ApiEncryptionKeySignature(privateKey.getKeyId(), "Ed25519", signature); } }; } public static final Supplier<PrivateKey> GENERATOR = new Supplier<PrivateKey>() { @Override public PrivateKey get() { Curve25519KeyPair keyPair = Curve25519.keyGen(Crypto.randomBytes(64)); return new PrivateKey( RandomUtils.nextRid(), "curve25519", keyPair.getPrivateKey(), keyPair.getPublicKey(), false); } }; public static final Predicate<PrivateKey> NOT_UPLOADED = new Predicate<PrivateKey>() { @Override public boolean apply(PrivateKey privateKey) { return !privateKey.isUploaded(); } }; public static final Predicate<PrivateKey> UPLOADED = new Predicate<PrivateKey>() { @Override public boolean apply(PrivateKey privateKey) { return privateKey.isUploaded(); } }; private long keyId; private String keyAlg; private byte[] key; private byte[] publicKey; private Boolean isUploaded; private boolean wasRegenerated = false; public PrivateKey(long keyId, String keyAlg, byte[] privateKey, byte[] publicKey, Boolean isUploaded) { this.keyId = keyId; this.keyAlg = keyAlg; this.key = privateKey; this.isUploaded = isUploaded; this.publicKey = publicKey; } public PrivateKey(long keyId, String keyAlg, byte[] privateKey, byte[] publicKey) { this(keyId, keyAlg, privateKey, publicKey, null); } public PrivateKey(byte[] data) throws IOException { load(data); } public long getKeyId() { return keyId; } public String getKeyAlg() { return keyAlg; } public byte[] getKey() { return key; } public byte[] getPublicKey() { return publicKey; } public boolean isUploaded() { if (isUploaded == null) { return false; } return isUploaded; } public boolean isWasRegenerated() { return wasRegenerated; } public ApiEncryptionKey toApiKey() { return new ApiEncryptionKey(keyId, keyAlg, publicKey, null); } public PrivateKey markAsUploaded() { return new PrivateKey(getKeyId(), getKeyAlg(), getKey(), getPublicKey(), true); } @Override public void parse(BserValues values) throws IOException { keyId = values.getLong(1); keyAlg = values.getString(2); key = values.getBytes(3); isUploaded = values.optBool(4); publicKey = values.optBytes(5); if (publicKey == null) { wasRegenerated = true; publicKey = Curve25519.keyGenPublic(key); } } @Override public void serialize(BserWriter writer) throws IOException { writer.writeLong(1, keyId); writer.writeString(2, keyAlg); writer.writeBytes(3, key); writer.writeBytes(5, publicKey); if (isUploaded != null) { writer.writeBool(4, isUploaded); } } }