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/ecc |
Break out into separate repo.
Diffstat (limited to '')
7 files changed, 370 insertions, 0 deletions
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java new file mode 100644 index 00000000..66b8cc3a --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package org.whispersystems.libaxolotl.ecc; + +import org.whispersystems.libaxolotl.InvalidKeyException; + +public class Curve { + + public static final int DJB_TYPE = 0x05; + + public static ECKeyPair generateKeyPair() { + return Curve25519.generateKeyPair(); + } + + public static ECPublicKey decodePoint(byte[] bytes, int offset) + throws InvalidKeyException + { + int type = bytes[offset]; + + if (type == DJB_TYPE) { + return Curve25519.decodePoint(bytes, offset); + } else { + throw new InvalidKeyException("Unknown key type: " + type); + } + } + + public static ECPrivateKey decodePrivatePoint(byte[] bytes) { + return new DjbECPrivateKey(bytes); + } + + public static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey) + throws InvalidKeyException + { + if (publicKey.getType() != privateKey.getType()) { + throw new InvalidKeyException("Public and private keys must be of the same type!"); + } + + if (publicKey.getType() == DJB_TYPE) { + return Curve25519.calculateAgreement(publicKey, privateKey); + } else { + throw new InvalidKeyException("Unknown type: " + publicKey.getType()); + } + } + + public static boolean verifySignature(ECPublicKey signingKey, byte[] message, byte[] signature) + throws InvalidKeyException + { + if (signingKey.getType() == DJB_TYPE) { + return Curve25519.verifySignature(signingKey, message, signature); + } else { + throw new InvalidKeyException("Unknown type: " + signingKey.getType()); + } + } + + public static byte[] calculateSignature(ECPrivateKey signingKey, byte[] message) + throws InvalidKeyException + { + if (signingKey.getType() == DJB_TYPE) { + return Curve25519.calculateSignature(signingKey, message); + } else { + throw new InvalidKeyException("Unknown type: " + signingKey.getType()); + } + } +} diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java new file mode 100644 index 00000000..685a4a11 --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package org.whispersystems.libaxolotl.ecc; + +import org.whispersystems.libaxolotl.InvalidKeyException; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +public class Curve25519 { + + static { + System.loadLibrary("curve25519"); + + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + private static final SecureRandom random; + + private static native byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic); + private static native byte[] generatePublicKey(byte[] privateKey); + private static native byte[] generatePrivateKey(byte[] random); + + private static native byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message); + private static native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature); + + public static ECKeyPair generateKeyPair() { + byte[] privateKey = generatePrivateKey(); + byte[] publicKey = generatePublicKey(privateKey); + + return new ECKeyPair(new DjbECPublicKey(publicKey), new DjbECPrivateKey(privateKey)); + } + + static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey) { + return calculateAgreement(((DjbECPrivateKey)privateKey).getPrivateKey(), + ((DjbECPublicKey)publicKey).getPublicKey()); + } + + static byte[] calculateSignature(ECPrivateKey privateKey, byte[] message) { + byte[] random = getRandom(64); + return calculateSignature(random, ((DjbECPrivateKey)privateKey).getPrivateKey(), message); + } + + static boolean verifySignature(ECPublicKey publicKey, byte[] message, byte[] signature) { + return verifySignature(((DjbECPublicKey)publicKey).getPublicKey(), message, signature); + } + + static ECPublicKey decodePoint(byte[] encoded, int offset) + throws InvalidKeyException + { + int type = encoded[offset] & 0xFF; + byte[] keyBytes = new byte[32]; + System.arraycopy(encoded, offset+1, keyBytes, 0, keyBytes.length); + + if (type != Curve.DJB_TYPE) { + throw new InvalidKeyException("Bad key type: " + type); + } + + return new DjbECPublicKey(keyBytes); + } + + private static byte[] generatePrivateKey() { + byte[] privateKey = new byte[32]; + random.nextBytes(privateKey); + + return generatePrivateKey(privateKey); + } + + private static byte[] getRandom(int size) { + try { + byte[] random = new byte[size]; + SecureRandom.getInstance("SHA1PRNG").nextBytes(random); + + return random; + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + +} diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java new file mode 100644 index 00000000..ecb55b4e --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.whispersystems.libaxolotl.ecc; + +public class DjbECPrivateKey implements ECPrivateKey { + + private final byte[] privateKey; + + DjbECPrivateKey(byte[] privateKey) { + this.privateKey = privateKey; + } + + @Override + public byte[] serialize() { + return privateKey; + } + + @Override + public int getType() { + return Curve.DJB_TYPE; + } + + public byte[] getPrivateKey() { + return privateKey; + } +} diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java new file mode 100644 index 00000000..9f66d439 --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.whispersystems.libaxolotl.ecc; + +import org.whispersystems.libaxolotl.util.ByteUtil; + +import java.math.BigInteger; +import java.util.Arrays; + +public class DjbECPublicKey implements ECPublicKey { + + private final byte[] publicKey; + + DjbECPublicKey(byte[] publicKey) { + this.publicKey = publicKey; + } + + @Override + public byte[] serialize() { + byte[] type = {Curve.DJB_TYPE}; + return ByteUtil.combine(type, publicKey); + } + + @Override + public int getType() { + return Curve.DJB_TYPE; + } + + @Override + public boolean equals(Object other) { + if (other == null) return false; + if (!(other instanceof DjbECPublicKey)) return false; + + DjbECPublicKey that = (DjbECPublicKey)other; + return Arrays.equals(this.publicKey, that.publicKey); + } + + @Override + public int hashCode() { + return Arrays.hashCode(publicKey); + } + + @Override + public int compareTo(ECPublicKey another) { + return new BigInteger(publicKey).compareTo(new BigInteger(((DjbECPublicKey)another).publicKey)); + } + + public byte[] getPublicKey() { + return publicKey; + } +} diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java b/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java new file mode 100644 index 00000000..bcaec927 --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.whispersystems.libaxolotl.ecc; + +public class ECKeyPair { + + private final ECPublicKey publicKey; + private final ECPrivateKey privateKey; + + public ECKeyPair(ECPublicKey publicKey, ECPrivateKey privateKey) { + this.publicKey = publicKey; + this.privateKey = privateKey; + } + + public ECPublicKey getPublicKey() { + return publicKey; + } + + public ECPrivateKey getPrivateKey() { + return privateKey; + } +} diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java new file mode 100644 index 00000000..922057de --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.whispersystems.libaxolotl.ecc; + +public interface ECPrivateKey { + public byte[] serialize(); + public int getType(); +} diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java new file mode 100644 index 00000000..12576807 --- /dev/null +++ b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2013 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.whispersystems.libaxolotl.ecc; + +public interface ECPublicKey extends Comparable<ECPublicKey> { + + public static final int KEY_SIZE = 33; + + public byte[] serialize(); + + public int getType(); +} |