]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/util/KeyUtils.java
Update libsignal-service-java
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / util / KeyUtils.java
1 package org.asamk.signal.manager.util;
2
3 import org.signal.libsignal.protocol.IdentityKey;
4 import org.signal.libsignal.protocol.IdentityKeyPair;
5 import org.signal.libsignal.protocol.InvalidKeyException;
6 import org.signal.libsignal.protocol.ecc.Curve;
7 import org.signal.libsignal.protocol.ecc.ECPrivateKey;
8 import org.signal.libsignal.protocol.kem.KEMKeyPair;
9 import org.signal.libsignal.protocol.kem.KEMKeyType;
10 import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
11 import org.signal.libsignal.protocol.state.PreKeyRecord;
12 import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
13 import org.signal.libsignal.zkgroup.InvalidInputException;
14 import org.signal.libsignal.zkgroup.profiles.ProfileKey;
15 import org.whispersystems.signalservice.api.kbs.MasterKey;
16
17 import java.security.SecureRandom;
18 import java.util.ArrayList;
19 import java.util.Base64;
20 import java.util.List;
21
22 import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_BATCH_SIZE;
23 import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_MAXIMUM_ID;
24
25 public class KeyUtils {
26
27 private static final SecureRandom secureRandom = new SecureRandom();
28
29 private KeyUtils() {
30 }
31
32 public static IdentityKeyPair getIdentityKeyPair(byte[] publicKeyBytes, byte[] privateKeyBytes) {
33 try {
34 IdentityKey publicKey = new IdentityKey(publicKeyBytes);
35 ECPrivateKey privateKey = Curve.decodePrivatePoint(privateKeyBytes);
36
37 return new IdentityKeyPair(publicKey, privateKey);
38 } catch (InvalidKeyException e) {
39 throw new AssertionError(e);
40 }
41 }
42
43 public static IdentityKeyPair generateIdentityKeyPair() {
44 var djbKeyPair = Curve.generateKeyPair();
45 var djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey());
46 var djbPrivateKey = djbKeyPair.getPrivateKey();
47
48 return new IdentityKeyPair(djbIdentityKey, djbPrivateKey);
49 }
50
51 public static List<PreKeyRecord> generatePreKeyRecords(final int offset) {
52 var records = new ArrayList<PreKeyRecord>(PREKEY_BATCH_SIZE);
53 for (var i = 0; i < PREKEY_BATCH_SIZE; i++) {
54 var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID;
55 var keyPair = Curve.generateKeyPair();
56 var record = new PreKeyRecord(preKeyId, keyPair);
57
58 records.add(record);
59 }
60 return records;
61 }
62
63 public static SignedPreKeyRecord generateSignedPreKeyRecord(
64 final int signedPreKeyId, final IdentityKeyPair identityKeyPair
65 ) {
66 var keyPair = Curve.generateKeyPair();
67 byte[] signature;
68 try {
69 signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
70 } catch (InvalidKeyException e) {
71 throw new AssertionError(e);
72 }
73 return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature);
74 }
75
76 public static List<KyberPreKeyRecord> generateKyberPreKeyRecords(
77 final int offset, final ECPrivateKey privateKey
78 ) {
79 var records = new ArrayList<KyberPreKeyRecord>(PREKEY_BATCH_SIZE);
80 for (var i = 0; i < PREKEY_BATCH_SIZE; i++) {
81 var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID;
82 records.add(generateKyberPreKeyRecord(preKeyId, privateKey));
83 }
84 return records;
85 }
86
87 public static KyberPreKeyRecord generateKyberPreKeyRecord(final int preKeyId, final ECPrivateKey privateKey) {
88 KEMKeyPair keyPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024);
89 byte[] signature = privateKey.calculateSignature(keyPair.getPublicKey().serialize());
90
91 return new KyberPreKeyRecord(preKeyId, System.currentTimeMillis(), keyPair, signature);
92 }
93
94 public static ProfileKey createProfileKey() {
95 try {
96 return new ProfileKey(getSecretBytes(32));
97 } catch (InvalidInputException e) {
98 throw new AssertionError("Profile key is guaranteed to be 32 bytes here");
99 }
100 }
101
102 public static String createPassword() {
103 return getSecret(18);
104 }
105
106 public static byte[] createStickerUploadKey() {
107 return getSecretBytes(32);
108 }
109
110 public static MasterKey createMasterKey() {
111 return MasterKey.createNew(secureRandom);
112 }
113
114 private static String getSecret(int size) {
115 var secret = getSecretBytes(size);
116 return Base64.getEncoder().encodeToString(secret);
117 }
118
119 public static byte[] getSecretBytes(int size) {
120 var secret = new byte[size];
121 secureRandom.nextBytes(secret);
122 return secret;
123 }
124
125 public static int getRandomInt(int bound) {
126 return secureRandom.nextInt(bound);
127 }
128 }