]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/util/KeyUtils.java
e6c97d440f3f4ec826be0e1337f9166221e5eea8
[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.zkgroup.InvalidInputException;
4 import org.signal.zkgroup.profiles.ProfileKey;
5 import org.whispersystems.libsignal.IdentityKey;
6 import org.whispersystems.libsignal.IdentityKeyPair;
7 import org.whispersystems.libsignal.InvalidKeyException;
8 import org.whispersystems.libsignal.ecc.Curve;
9 import org.whispersystems.libsignal.ecc.ECPrivateKey;
10 import org.whispersystems.libsignal.state.PreKeyRecord;
11 import org.whispersystems.libsignal.state.SignedPreKeyRecord;
12 import org.whispersystems.libsignal.util.Medium;
13 import org.whispersystems.signalservice.api.kbs.MasterKey;
14
15 import java.security.SecureRandom;
16 import java.util.ArrayList;
17 import java.util.Base64;
18 import java.util.List;
19
20 public class KeyUtils {
21
22 private static final SecureRandom secureRandom = new SecureRandom();
23
24 private KeyUtils() {
25 }
26
27 public static IdentityKeyPair getIdentityKeyPair(byte[] publicKeyBytes, byte[] privateKeyBytes) {
28 try {
29 IdentityKey publicKey = new IdentityKey(publicKeyBytes);
30 ECPrivateKey privateKey = Curve.decodePrivatePoint(privateKeyBytes);
31
32 return new IdentityKeyPair(publicKey, privateKey);
33 } catch (InvalidKeyException e) {
34 throw new AssertionError(e);
35 }
36 }
37
38 public static IdentityKeyPair generateIdentityKeyPair() {
39 var djbKeyPair = Curve.generateKeyPair();
40 var djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey());
41 var djbPrivateKey = djbKeyPair.getPrivateKey();
42
43 return new IdentityKeyPair(djbIdentityKey, djbPrivateKey);
44 }
45
46 public static List<PreKeyRecord> generatePreKeyRecords(final int offset, final int batchSize) {
47 var records = new ArrayList<PreKeyRecord>(batchSize);
48 for (var i = 0; i < batchSize; i++) {
49 var preKeyId = (offset + i) % Medium.MAX_VALUE;
50 var keyPair = Curve.generateKeyPair();
51 var record = new PreKeyRecord(preKeyId, keyPair);
52
53 records.add(record);
54 }
55 return records;
56 }
57
58 public static SignedPreKeyRecord generateSignedPreKeyRecord(
59 final IdentityKeyPair identityKeyPair, final int signedPreKeyId
60 ) {
61 var keyPair = Curve.generateKeyPair();
62 byte[] signature;
63 try {
64 signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
65 } catch (InvalidKeyException e) {
66 throw new AssertionError(e);
67 }
68 return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature);
69 }
70
71 public static ProfileKey createProfileKey() {
72 try {
73 return new ProfileKey(getSecretBytes(32));
74 } catch (InvalidInputException e) {
75 throw new AssertionError("Profile key is guaranteed to be 32 bytes here");
76 }
77 }
78
79 public static String createPassword() {
80 return getSecret(18);
81 }
82
83 public static byte[] createStickerUploadKey() {
84 return getSecretBytes(32);
85 }
86
87 public static MasterKey createMasterKey() {
88 return MasterKey.createNew(secureRandom);
89 }
90
91 private static String getSecret(int size) {
92 var secret = getSecretBytes(size);
93 return Base64.getEncoder().encodeToString(secret);
94 }
95
96 public static byte[] getSecretBytes(int size) {
97 var secret = new byte[size];
98 secureRandom.nextBytes(secret);
99 return secret;
100 }
101 }