diff options
Diffstat (limited to 'java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java')
-rw-r--r-- | java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java new file mode 100644 index 00000000..5d47e3aa --- /dev/null +++ b/java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java @@ -0,0 +1,103 @@ +/** + * 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.curve25519.Curve25519KeyPair; +import org.whispersystems.libaxolotl.InvalidKeyException; +import org.whispersystems.curve25519.Curve25519; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +public class Curve { + + public static final int DJB_TYPE = 0x05; + + public static boolean isNative() { + return Curve25519.isNative(); + } + + public static ECKeyPair generateKeyPair() { + SecureRandom secureRandom = getSecureRandom(); + Curve25519KeyPair keyPair = Curve25519.generateKeyPair(secureRandom); + + return new ECKeyPair(new DjbECPublicKey(keyPair.getPublicKey()), + new DjbECPrivateKey(keyPair.getPrivateKey())); + } + + public static ECPublicKey decodePoint(byte[] bytes, int offset) + throws InvalidKeyException + { + int type = bytes[offset] & 0xFF; + + switch (type) { + case Curve.DJB_TYPE: + byte[] keyBytes = new byte[32]; + System.arraycopy(bytes, offset+1, keyBytes, 0, keyBytes.length); + return new DjbECPublicKey(keyBytes); + default: + throw new InvalidKeyException("Bad 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(((DjbECPublicKey)publicKey).getPublicKey(), + ((DjbECPrivateKey)privateKey).getPrivateKey()); + } 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(((DjbECPublicKey)signingKey).getPublicKey(), 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(getSecureRandom(), ((DjbECPrivateKey)signingKey).getPrivateKey(), message); + } else { + throw new InvalidKeyException("Unknown type: " + signingKey.getType()); + } + } + + private static SecureRandom getSecureRandom() { + try { + return SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } +} |