Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Commit

Permalink
Allow caller to specify Random interface, mostly for J2ME.
Browse files Browse the repository at this point in the history
  • Loading branch information
moxie0 committed Feb 2, 2015
1 parent f0cfecb commit 8bc4332
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 120 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/**
* Copyright (C) 2015 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/>.
*/
* Copyright (C) 2015 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.curve25519;

import org.whispersystems.curve25519.java.Sha512;
Expand All @@ -22,34 +22,41 @@

abstract class BaseJavaCurve25519Provider implements Curve25519Provider {

// @Override
public boolean isNative() {
return false;
private final Sha512 sha512provider;
private SecureRandomProvider secureRandomProvider;

protected BaseJavaCurve25519Provider(Sha512 sha512provider,
SecureRandomProvider secureRandomProvider)
{
this.sha512provider = sha512provider;
this.secureRandomProvider = secureRandomProvider;
}

public abstract boolean isNative();

public void setRandomProvider(SecureRandomProvider secureRandomProvider) {
this.secureRandomProvider = secureRandomProvider;
}

// @Override
public byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic) {
byte[] agreement = new byte[32];
scalarmult.crypto_scalarmult(agreement, ourPrivate, theirPublic);

return agreement;
}

// @Override
public byte[] generatePublicKey(byte[] privateKey) {
byte[] publicKey = new byte[32];
curve_sigs.curve25519_keygen(publicKey, privateKey);

return publicKey;
}

// @Override
public byte[] generatePrivateKey() {
byte[] random = getRandom(PRIVATE_KEY_LEN);
return generatePrivateKey(random);
}

// @Override
public byte[] generatePrivateKey(byte[] random) {
byte[] privateKey = new byte[32];

Expand All @@ -62,22 +69,23 @@ public byte[] generatePrivateKey(byte[] random) {
return privateKey;
}

// @Override
public byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message) {
byte[] result = new byte[64];

if (curve_sigs.curve25519_sign(getSha512(), result, privateKey, message, message.length, random) != 0) {
if (curve_sigs.curve25519_sign(sha512provider, result, privateKey, message, message.length, random) != 0) {
throw new IllegalArgumentException("Message exceeds max length!");
}

return result;
}

// @Override
public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature) {
return curve_sigs.curve25519_verify(getSha512(), signature, publicKey, message, message.length) == 0;
return curve_sigs.curve25519_verify(sha512provider, signature, publicKey, message, message.length) == 0;
}

protected abstract Sha512 getSha512();

public byte[] getRandom(int length) {
byte[] result = new byte[length];
secureRandomProvider.nextBytes(result);
return result;
}
}
63 changes: 26 additions & 37 deletions common/src/main/java/org/whispersystems/curve25519/Curve25519.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ public class Curve25519 {
public static final String BEST = "best";

public static Curve25519 getInstance(String type) throws NoSuchProviderException {
if (NATIVE.equals(type)) return new Curve25519(constructNativeProvider());
else if (JAVA.equals(type)) return new Curve25519(constructJavaProvider());
else if (J2ME.equals(type)) return new Curve25519(constructJ2meProvider());
else if (BEST.equals(type)) return new Curve25519(constructOpportunisticProvider());
return getInstance(type, null);
}

public static Curve25519 getInstance(String type, SecureRandomProvider random)
throws NoSuchProviderException
{
if (NATIVE.equals(type)) return new Curve25519(constructNativeProvider(random));
else if (JAVA.equals(type)) return new Curve25519(constructJavaProvider(random));
else if (J2ME.equals(type)) return new Curve25519(constructJ2meProvider(random));
else if (BEST.equals(type)) return new Curve25519(constructOpportunisticProvider(random));
else throw new NoSuchProviderException(type);
}

Expand All @@ -43,15 +49,6 @@ private Curve25519(Curve25519Provider provider) {
this.provider = provider;
}


// static {
// try {
// provider = new NativeCurve25519Provider();
// } catch (UnsatisfiedLinkError ule) {
// provider = new JavaCurve25519Provider();
// }
// }

/**
* {@link Curve25519} is backed by either a native (via JNI)
* or pure-Java provider. By default it prefers the native provider, and falls back to the
Expand Down Expand Up @@ -110,39 +107,31 @@ public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signatur
return provider.verifySignature(publicKey, message, signature);
}

// private byte[] generatePrivateKey() {
// byte[] privateKey = new byte[32];
// random.nextBytes(privateKey);
//
// return provider.generatePrivateKey(privateKey);
// }

// private byte[] getRandom(SecureRandom secureRandom, int size) {
// byte[] output = new byte[size];
// secureRandom.nextBytes(output);
//
// return output;
// }

private static Curve25519Provider constructNativeProvider() throws NoSuchProviderException {
return constructClass("NativeCurve25519Provider");
private static Curve25519Provider constructNativeProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("NativeCurve25519Provider", random);
}

private static Curve25519Provider constructJavaProvider() throws NoSuchProviderException {
return constructClass("JavaCurve25519Provider");
private static Curve25519Provider constructJavaProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("JavaCurve25519Provider", random);
}

private static Curve25519Provider constructJ2meProvider() throws NoSuchProviderException {
return constructClass("J2meCurve25519Provider");
private static Curve25519Provider constructJ2meProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("J2meCurve25519Provider", random);
}

private static Curve25519Provider constructOpportunisticProvider() throws NoSuchProviderException {
return constructClass("OpportunisticCurve25519Provider");
private static Curve25519Provider constructOpportunisticProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("OpportunisticCurve25519Provider", random);
}

private static Curve25519Provider constructClass(String name) throws NoSuchProviderException {
private static Curve25519Provider constructClass(String name, SecureRandomProvider random) throws NoSuchProviderException {
try {
return (Curve25519Provider)Class.forName("org.whispersystems.curve25519." + name).newInstance();
Curve25519Provider provider = (Curve25519Provider)Class.forName("org.whispersystems.curve25519." + name).newInstance();

if (random != null) {
provider.setRandomProvider(random);
}

return provider;
} catch (InstantiationException e) {
throw new NoSuchProviderException(e);
} catch (IllegalAccessException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ interface Curve25519Provider {
byte[] generatePublicKey(byte[] privateKey);
byte[] generatePrivateKey();
byte[] generatePrivateKey(byte[] random);
byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message);
boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
byte[] getRandom(int length);

byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message);
boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
void setRandomProvider(SecureRandomProvider provider);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.whispersystems.curve25519;

public interface SecureRandomProvider {
public void nextBytes(byte[] output);
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
package org.whispersystems.curve25519;

import org.whispersystems.curve25519.java.Sha512;

public class J2meCurve25519Provider extends BaseJavaCurve25519Provider {

private final BouncyCastleSha512Provider sha512Provider = new BouncyCastleSha512Provider();

// @Override
protected Sha512 getSha512() {
return sha512Provider;
protected J2meCurve25519Provider() {
super(new BouncyCastleSha512Provider(), new NullSecureRandomProvider());
}

// @Override
public byte[] getRandom(int length) {
byte[] random = new byte[length];
SecureRandom.getInstance().nextBytes(random);

return random;
@Override
public boolean isNative() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.whispersystems.curve25519;

public class NullSecureRandomProvider implements SecureRandomProvider {
@Override
public void nextBytes(byte[] output) {
throw new IllegalArgumentException("No default J2ME Secure Random provider available!");
}
}
14 changes: 0 additions & 14 deletions j2me/src/main/java/org/whispersystems/curve25519/SecureRandom.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.whispersystems.curve25519;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class JCESecureRandomProvider implements SecureRandomProvider {

@Override
public void nextBytes(byte[] output) {
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.nextBytes(output);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,13 @@

public class JavaCurve25519Provider extends BaseJavaCurve25519Provider {

private final JCESha512Provider sha512Provider = new JCESha512Provider();

@Override
protected Sha512 getSha512() {
return sha512Provider;
protected JavaCurve25519Provider() {
super(new JCESha512Provider(), new JCESecureRandomProvider());
}

@Override
public byte[] getRandom(int length) {
try {
byte[] random = new byte[length];
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.nextBytes(random);

return random;
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
public boolean isNative() {
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
*/
package org.whispersystems.curve25519;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

class NativeCurve25519Provider implements Curve25519Provider {

private static boolean libraryPresent = false;
Expand All @@ -34,6 +31,8 @@ class NativeCurve25519Provider implements Curve25519Provider {
}
}

private SecureRandomProvider secureRandomProvider = new JCESecureRandomProvider();

NativeCurve25519Provider() throws NoSuchProviderException {
if (!libraryPresent) throw new NoSuchProviderException(libraryFailedException);
}
Expand All @@ -52,18 +51,14 @@ public byte[] generatePrivateKey() {
@Override
public byte[] getRandom(int length) {
byte[] result = new byte[length];
setRandom(result);
secureRandomProvider.nextBytes(result);

return result;
}

private void setRandom(byte[] output) {
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.nextBytes(output);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
@Override
public void setRandomProvider(SecureRandomProvider provider) {
this.secureRandomProvider = provider;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public byte[] getRandom(int length) {
return delegate.getRandom(length);
}

@Override
public void setRandomProvider(SecureRandomProvider provider) {
delegate.setRandomProvider(provider);
}

@Override
public byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message) {
return delegate.calculateSignature(random, privateKey, message);
Expand Down

0 comments on commit 8bc4332

Please sign in to comment.