diff options
author | Moxie Marlinspike <moxie@thoughtcrime.org> | 2014-11-24 12:54:30 -0800 |
---|---|---|
committer | Moxie Marlinspike <moxie@thoughtcrime.org> | 2014-11-24 12:54:30 -0800 |
commit | 60800e155612bea797eed93c67046a23d26054cc (patch) | |
tree | d88368c1c26162e27e790195133ca2b526597afe /src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java |
Break out into separate repo.
Diffstat (limited to 'src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java')
-rw-r--r-- | src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java b/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java new file mode 100644 index 00000000..96ee6563 --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java @@ -0,0 +1,143 @@ +package org.whispersystems.libaxolotl.util; + +import org.whispersystems.libaxolotl.IdentityKey; +import org.whispersystems.libaxolotl.IdentityKeyPair; +import org.whispersystems.libaxolotl.InvalidKeyException; +import org.whispersystems.libaxolotl.ecc.Curve; +import org.whispersystems.libaxolotl.ecc.ECKeyPair; +import org.whispersystems.libaxolotl.state.PreKeyRecord; +import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.LinkedList; +import java.util.List; + +/** + * Helper class for generating keys of different types. + * + * @author Moxie Marlinspike + */ +public class KeyHelper { + + private KeyHelper() {} + + /** + * Generate an identity key pair. Clients should only do this once, + * at install time. + * + * @return the generated IdentityKeyPair. + */ + public static IdentityKeyPair generateIdentityKeyPair() { + ECKeyPair keyPair = Curve.generateKeyPair(); + IdentityKey publicKey = new IdentityKey(keyPair.getPublicKey()); + return new IdentityKeyPair(publicKey, keyPair.getPrivateKey()); + } + + /** + * Generate a registration ID. Clients should only do this once, + * at install time. + * + * @param extendedRange By default (false), the generated registration + * ID is sized to require the minimal possible protobuf + * encoding overhead. Specify true if the caller needs + * the full range of MAX_INT at the cost of slightly + * higher encoding overhead. + * @return the generated registration ID. + */ + public static int generateRegistrationId(boolean extendedRange) { + try { + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); + if (extendedRange) return secureRandom.nextInt(Integer.MAX_VALUE - 1) + 1; + else return secureRandom.nextInt(16380) + 1; + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + public static int getRandomSequence(int max) { + try { + return SecureRandom.getInstance("SHA1PRNG").nextInt(max); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + /** + * Generate a list of PreKeys. Clients should do this at install time, and + * subsequently any time the list of PreKeys stored on the server runs low. + * <p> + * PreKey IDs are shorts, so they will eventually be repeated. Clients should + * store PreKeys in a circular buffer, so that they are repeated as infrequently + * as possible. + * + * @param start The starting PreKey ID, inclusive. + * @param count The number of PreKeys to generate. + * @return the list of generated PreKeyRecords. + */ + public static List<PreKeyRecord> generatePreKeys(int start, int count) { + List<PreKeyRecord> results = new LinkedList<>(); + + start--; + + for (int i=0;i<count;i++) { + results.add(new PreKeyRecord(((start + i) % (Medium.MAX_VALUE-1)) + 1, Curve.generateKeyPair())); + } + + return results; + } + + /** + * Generate the last resort PreKey. Clients should do this only once, at install + * time, and durably store it for the length of the install. + * + * @return the generated last resort PreKeyRecord. + */ + public static PreKeyRecord generateLastResortPreKey() { + ECKeyPair keyPair = Curve.generateKeyPair(); + return new PreKeyRecord(Medium.MAX_VALUE, keyPair); + } + + /** + * Generate a signed PreKey + * + * @param identityKeyPair The local client's identity key pair. + * @param signedPreKeyId The PreKey id to assign the generated signed PreKey + * + * @return the generated signed PreKey + * @throws InvalidKeyException when the provided identity key is invalid + */ + public static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair, int signedPreKeyId) + throws InvalidKeyException + { + ECKeyPair keyPair = Curve.generateKeyPair(); + byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize()); + + return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature); + } + + + public static ECKeyPair generateSenderSigningKey() { + return Curve.generateKeyPair(); + } + + public static byte[] generateSenderKey() { + try { + byte[] key = new byte[32]; + SecureRandom.getInstance("SHA1PRNG").nextBytes(key); + + return key; + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + public static int generateSenderKeyId() { + try { + return SecureRandom.getInstance("SHA1PRNG").nextInt(Integer.MAX_VALUE); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + +} |