Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-06-21 12:16:37 +0400
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-06-21 12:16:37 +0400
commit2e05e49616ffaea79bcde9d578486b51408718a4 (patch)
treef9cb0ee6d49487d70fad72cb60e36115c3454078 /core/src/main/java/org/bouncycastle/crypto
parent17a8e3bd2d36580e8f49484341960137f724a3e7 (diff)
parenta51207405bebf737c2dcae501dd8c02c9c2cd88a (diff)
Merge branch 'master' of https://github.com/franziskuskiefer/bc-java into franziskuskiefer-master
Conflicts: .gitignore
Diffstat (limited to 'core/src/main/java/org/bouncycastle/crypto')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java162
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java266
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java63
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java112
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java24
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java40
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java53
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java61
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java42
9 files changed, 823 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java
new file mode 100644
index 00000000..1e43eb2a
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java
@@ -0,0 +1,162 @@
+package org.bouncycastle.crypto.engines;
+
+import java.math.BigInteger;
+
+/**
+ *
+ * Class, holding Cramer Shoup ciphertexts (u1, u2, e, v)
+ *
+ */
+public class CramerShoupCiphertext {
+
+ BigInteger u1, u2, e, v;
+
+ public CramerShoupCiphertext() {
+
+ }
+
+ public CramerShoupCiphertext(BigInteger u1, BigInteger u2, BigInteger e, BigInteger v){
+ this.u1 = u1;
+ this.u2 = u2;
+ this.e = e;
+ this.v = v;
+ }
+
+ public CramerShoupCiphertext(byte[] c){
+ int off = 0, s;
+ byte[] size = new byte[4];
+ byte[] tmp;
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ u1 = new BigInteger(tmp);
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ u2 = new BigInteger(tmp);
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ e = new BigInteger(tmp);
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ v = new BigInteger(tmp);
+ }
+
+ public BigInteger getU1() {
+ return u1;
+ }
+
+ public void setU1(BigInteger u1) {
+ this.u1 = u1;
+ }
+
+ public BigInteger getU2() {
+ return u2;
+ }
+
+ public void setU2(BigInteger u2) {
+ this.u2 = u2;
+ }
+
+ public BigInteger getE() {
+ return e;
+ }
+
+ public void setE(BigInteger e) {
+ this.e = e;
+ }
+
+ public BigInteger getV() {
+ return v;
+ }
+
+ public void setV(BigInteger v) {
+ this.v = v;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+
+ result.append("u1: "+u1.toString());
+ result.append("\nu2: "+u2.toString());
+ result.append("\ne: "+e.toString());
+ result.append("\nv: "+v.toString());
+
+ return result.toString();
+ }
+
+ /**
+ * convert the cipher-text in a byte array,
+ * prepending them with 4 Bytes for their length
+ *
+ * @return
+ */
+ public byte[] toByteArray(){
+
+ byte[] u1Bytes = u1.toByteArray();
+ int u1Length = u1Bytes.length;
+ byte[] u2Bytes = u2.toByteArray();
+ int u2Length = u2Bytes.length;
+ byte[] eBytes = e.toByteArray();
+ int eLength = eBytes.length;
+ byte[] vBytes = v.toByteArray();
+ int vLength = vBytes.length;
+
+ int off = 0;
+ byte[] result = new byte[u1Length+u2Length+eLength+vLength+4*4];
+ System.arraycopy(intToByteArray(u1Length), 0, result, 0, 4);
+ off += 4;
+ System.arraycopy(u1Bytes, 0, result, off, u1Length);
+ off += u1Length;
+ System.arraycopy(intToByteArray(u2Length), 0, result, off, 4);
+ off += 4;
+ System.arraycopy(u2Bytes, 0, result, off , u2Length);
+ off += u2Length;
+ System.arraycopy(intToByteArray(eLength), 0, result, off, 4);
+ off += 4;
+ System.arraycopy(eBytes, 0, result, off, eLength);
+ off += eLength;
+ System.arraycopy(intToByteArray(vLength), 0, result, off, 4);
+ off += 4;
+ System.arraycopy(vBytes, 0, result, off, vLength);
+
+ return result;
+ }
+
+ private byte[] intToByteArray(int in){
+ byte[] bytes = new byte[4];
+ for (int i = 0; i < 4; i++) {
+ bytes[3-i] = (byte)(in >>> (i * 8));
+ }
+ return bytes;
+ }
+
+ private int byteArrayToInt(byte[] in){
+ if (in.length != 4)
+ return -1;
+ int r = 0;
+ for (int i = 3; i >= 0; i--) {
+ r += (int)in[i] << ((3-i) * 8);
+ }
+ return r;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java
new file mode 100644
index 00000000..71cab278
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java
@@ -0,0 +1,266 @@
+package org.bouncycastle.crypto.engines;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.params.CramerShoupKeyParameters;
+import org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters;
+import org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.util.BigIntegers;
+
+/**
+ *
+ * Essentially the Cramer-Shoup encryption / decryption algorithms according to
+ * "A practical public key cryptosystem provably secure against adaptive chosen ciphertext attack." (Crypto 1998)
+ *
+ */
+public class CramerShoupCoreEngine {
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ private CramerShoupKeyParameters key;
+ private boolean forEncryption;
+ private String label = null;
+
+ /**
+ * initialise the CramerShoup engine.
+ *
+ * @param enc
+ * whether this engine should encrypt or decrypt
+ * @param param
+ * the necessary CramerShoup key parameters.
+ * @param label
+ * the label for labelled CS as {@link String}
+ */
+ public void init(boolean enc, CipherParameters param, String label) {
+ init(enc, param);
+
+ this.label = label;
+ }
+
+ /**
+ * initialise the CramerShoup engine.
+ *
+ * @param enc
+ * whether this engine should encrypt or decrypt
+ * @param param
+ * the necessary CramerShoup key parameters.
+ */
+ public void init(boolean enc, CipherParameters param) {
+ if (param instanceof ParametersWithRandom) {
+ ParametersWithRandom rParam = (ParametersWithRandom) param;
+
+ key = (CramerShoupKeyParameters) rParam.getParameters();
+ } else {
+ key = (CramerShoupKeyParameters) param;
+ }
+
+ this.forEncryption = enc;
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine. For Cramer
+ * Shoup this is always one byte less than the key size on encryption, and
+ * the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ *
+ * TODO: correct?
+ */
+ public int getInputBlockSize() {
+ int bitSize = key.getParameters().getP().bitLength();
+
+ if (forEncryption) {
+ return (bitSize + 7) / 8 - 1;
+ } else {
+ return (bitSize + 7) / 8;
+ }
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine. For Cramer
+ * Shoup this is always one byte less than the key size on decryption, and
+ * the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ *
+ * TODO: correct?
+ */
+ public int getOutputBlockSize() {
+ int bitSize = key.getParameters().getP().bitLength();
+
+ if (forEncryption) {
+ return (bitSize + 7) / 8;
+ } else {
+ return (bitSize + 7) / 8 - 1;
+ }
+ }
+
+ public BigInteger convertInput(byte[] in, int inOff, int inLen) {
+ if (inLen > (getInputBlockSize() + 1)) {
+ throw new DataLengthException("input too large for Cramer Shoup cipher.");
+ } else if (inLen == (getInputBlockSize() + 1) && !forEncryption) {
+ throw new DataLengthException("input too large for Cramer Shoup cipher.");
+ }
+
+ byte[] block;
+
+ if (inOff != 0 || inLen != in.length) {
+ block = new byte[inLen];
+
+ System.arraycopy(in, inOff, block, 0, inLen);
+ } else {
+ block = in;
+ }
+
+ BigInteger res = new BigInteger(1, block);
+ if (res.compareTo(key.getParameters().getP()) >= 0) {
+ throw new DataLengthException("input too large for Cramer Shoup cipher.");
+ }
+
+ return res;
+ }
+
+ public byte[] convertOutput(BigInteger result) {
+ byte[] output = result.toByteArray();
+
+ if (forEncryption) {
+ if (output[0] == 0 && output.length > getOutputBlockSize()) { // have ended up with an extra zero byte, copy down.
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ if (output.length < getOutputBlockSize()) {// have ended up with less bytes than normal, lengthen
+ byte[] tmp = new byte[getOutputBlockSize()];
+
+ System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
+
+ return tmp;
+ }
+ } else {
+ if (output[0] == 0) { // have ended up with an extra zero byte, copy down.
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+ }
+
+ return output;
+ }
+
+ public CramerShoupCiphertext encryptBlock(BigInteger input) {
+
+ CramerShoupCiphertext result = null;
+
+
+ if (!key.isPrivate() && !this.forEncryption && key instanceof CramerShoupPublicKeyParameters) {
+ CramerShoupPublicKeyParameters pk = (CramerShoupPublicKeyParameters)key;
+ BigInteger p = pk.getParameters().getP();
+ BigInteger g1 = pk.getParameters().getG1();
+ BigInteger g2 = pk.getParameters().getG2();
+
+ BigInteger h = pk.getH();
+
+ if (!isValidMessage(input, p))
+ return result;
+
+ BigInteger r = generateRandomElement(p, new SecureRandom());
+
+ BigInteger u1, u2, v, e, a;
+
+ u1 = g1.modPow(r, p);
+ u2 = g2.modPow(r, p);
+ e = h.modPow(r, p).multiply(input).mod(p);
+
+ Digest digest = pk.getParameters().getH();
+ byte[] u1Bytes = u1.toByteArray();
+ digest.update(u1Bytes, 0, u1Bytes.length);
+ byte[] u2Bytes = u2.toByteArray();
+ digest.update(u2Bytes, 0, u2Bytes.length);
+ byte[] eBytes = e.toByteArray();
+ digest.update(eBytes, 0, eBytes.length);
+ if (this.label != null){
+ byte[] lBytes = this.label.getBytes();
+ digest.update(lBytes, 0, lBytes.length);
+ }
+ byte[] out = new byte[digest.getDigestSize()];
+ digest.doFinal(out , 0);
+ a = new BigInteger(1, out);
+
+ v = pk.getC().modPow(r, p).multiply(pk.getD().modPow(r.multiply(a), p)).mod(p);
+
+ result = new CramerShoupCiphertext(u1, u2, e, v);
+ }
+ return result;
+ }
+
+ public BigInteger decryptBlock(CramerShoupCiphertext input) throws CramerShoupCiphertextException {
+
+ BigInteger result = null;
+
+ if (key.isPrivate() && this.forEncryption && key instanceof CramerShoupPrivateKeyParameters) {
+ CramerShoupPrivateKeyParameters sk = (CramerShoupPrivateKeyParameters)key;
+
+ BigInteger p = sk.getParameters().getP();
+
+ Digest digest = sk.getParameters().getH();
+ byte[] u1Bytes = input.getU1().toByteArray();
+ digest.update(u1Bytes, 0, u1Bytes.length);
+ byte[] u2Bytes = input.getU2().toByteArray();
+ digest.update(u2Bytes, 0, u2Bytes.length);
+ byte[] eBytes = input.getE().toByteArray();
+ digest.update(eBytes, 0, eBytes.length);
+ if (this.label != null){
+ byte[] lBytes = this.label.getBytes();
+ digest.update(lBytes, 0, lBytes.length);
+ }
+ byte[] out = new byte[digest.getDigestSize()];
+ digest.doFinal(out , 0);
+
+ BigInteger a = new BigInteger(1, out);
+ BigInteger v = input.u1.modPow(sk.getX1().add(sk.getY1().multiply(a)), p).
+ multiply(input.u2.modPow(sk.getX2().add(sk.getY2().multiply(a)), p)).mod(p);
+
+ // check correctness of ciphertext
+ if (input.v.equals(v)){
+ result = input.e.multiply(input.u1.modPow(sk.getZ(), p).modInverse(p)).mod(p);
+ } else {
+ throw new CramerShoupCiphertextException("Sorry, that ciphertext is not correct");
+ }
+ }
+ return result;
+ }
+
+ private BigInteger generateRandomElement(BigInteger p, SecureRandom random) {
+ return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
+ }
+
+ /**
+ * just checking whether the message m is actually less than the group order p
+ */
+ private boolean isValidMessage(BigInteger m, BigInteger p){
+ return m.compareTo(p) < 0;
+ }
+
+ /**
+ * CS exception for wrong cipher-texts
+ */
+ public class CramerShoupCiphertextException extends Exception {
+
+ private static final long serialVersionUID = -6360977166495345076L;
+
+ public CramerShoupCiphertextException(String msg) {
+ super(msg);
+ }
+
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java
new file mode 100644
index 00000000..8fcdf858
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java
@@ -0,0 +1,63 @@
+package org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.bouncycastle.crypto.KeyGenerationParameters;
+import org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters;
+import org.bouncycastle.crypto.params.CramerShoupParameters;
+import org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters;
+import org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters;
+import org.bouncycastle.util.BigIntegers;
+
+/**
+ * a Cramer Shoup key pair generator
+ *
+ */
+public class CramerShoupKeyPairGenerator implements AsymmetricCipherKeyPairGenerator {
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private CramerShoupKeyGenerationParameters param;
+
+ public void init(KeyGenerationParameters param) {
+ this.param = (CramerShoupKeyGenerationParameters) param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair() {
+ CramerShoupParameters csParams = param.getParameters();
+
+ CramerShoupPrivateKeyParameters sk = generatePrivateKey(param.getRandom(), csParams);
+ CramerShoupPublicKeyParameters pk = calculatePublicKey(csParams, sk);
+ sk.setPk(pk);
+
+ return new AsymmetricCipherKeyPair(pk, sk);
+ }
+
+ private BigInteger generateRandomElement(BigInteger p, SecureRandom random) {
+ return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
+ }
+
+ private CramerShoupPrivateKeyParameters generatePrivateKey(SecureRandom random, CramerShoupParameters csParams){
+ BigInteger p = csParams.getP();
+ CramerShoupPrivateKeyParameters key = new CramerShoupPrivateKeyParameters(csParams,
+ generateRandomElement(p, random), generateRandomElement(p, random),
+ generateRandomElement(p, random), generateRandomElement(p, random),
+ generateRandomElement(p, random));
+ return key;
+ }
+
+ private CramerShoupPublicKeyParameters calculatePublicKey(CramerShoupParameters csParams, CramerShoupPrivateKeyParameters sk) {
+ BigInteger g1 = csParams.getG1();
+ BigInteger g2 = csParams.getG2();
+ BigInteger p = csParams.getP();
+
+ BigInteger c = g1.modPow(sk.getX1(), p).multiply(g2.modPow(sk.getX2(), p));
+ BigInteger d = g1.modPow(sk.getY1(), p).multiply(g2.modPow(sk.getY2(), p));
+ BigInteger h = g1.modPow(sk.getZ(), p);
+
+ return new CramerShoupPublicKeyParameters(csParams, c, d, h);
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java
new file mode 100644
index 00000000..704b1de4
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java
@@ -0,0 +1,112 @@
+package org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.params.CramerShoupParameters;
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.util.BigIntegers;
+
+public class CramerShoupParametersGenerator {
+
+ private int size;
+ private int certainty;
+ private SecureRandom random;
+
+ /**
+ * Initialise the parameters generator.
+ *
+ * @param size
+ * bit length for the prime p
+ * @param certainty
+ * a measure of the uncertainty that the caller is willing to tolerate:
+ * the probability that the generated modulus is prime exceeds (1 - 1/2^certainty).
+ * The execution time of this method is proportional to the value of this parameter.
+ * @param random
+ * a source of randomness
+ */
+ public void init(int size, int certainty, SecureRandom random) {
+ this.size = size;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters, returning
+ * the CramerShoupParameters object.
+ * <p>
+ * Note: can take a while...
+ */
+ public CramerShoupParameters generateParameters() {
+ //
+ // find a safe prime p where p = 2*q + 1, where p and q are prime.
+ //
+ BigInteger[] safePrimes = ParametersHelper.generateSafePrimes(size, certainty, random);
+
+// BigInteger p = safePrimes[0];
+ BigInteger q = safePrimes[1];
+ BigInteger g1 = ParametersHelper.selectGenerator(q, random);
+ BigInteger g2 = ParametersHelper.selectGenerator(q, random);
+ while(g1.equals(g2)){
+ g2 = ParametersHelper.selectGenerator(q, random);
+ }
+
+ return new CramerShoupParameters(q, g1, g2, new SHA256Digest());
+ }
+
+ public CramerShoupParameters generateParameters(DHParameters dhParams){
+ BigInteger p = dhParams.getP();
+ BigInteger g1 = dhParams.getG();
+
+ // now we just need a second generator
+ BigInteger g2 = ParametersHelper.selectGenerator(p, random);
+ while(g1.equals(g2)){
+ g2 = ParametersHelper.selectGenerator(p, random);
+ }
+
+ return new CramerShoupParameters(p, g1, g2, new SHA256Digest());
+ }
+
+ private static class ParametersHelper {
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /*
+ * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
+ *
+ * (see: Handbook of Applied Cryptography 4.86)
+ */
+ static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random) {
+ BigInteger p, q;
+ int qLength = size - 1;
+
+ for (;;) {
+ q = new BigInteger(qLength, 2, random);
+ p = q.shiftLeft(1).add(BigInteger.ONE);
+ if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty))) {
+ break;
+ }
+ }
+
+ return new BigInteger[] { p, q };
+ }
+
+ static BigInteger selectGenerator(BigInteger p, SecureRandom random) {
+ BigInteger pMinusTwo = p.subtract(TWO);
+ BigInteger g;
+
+ /*
+ * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
+ */
+ do {
+ BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
+
+ g = h.modPow(TWO, p);
+ } while (g.equals(BigInteger.ONE));
+
+ return g;
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java
new file mode 100644
index 00000000..15b6d6a5
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java
@@ -0,0 +1,24 @@
+package org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.KeyGenerationParameters;
+
+public class CramerShoupKeyGenerationParameters extends KeyGenerationParameters {
+
+ private CramerShoupParameters params;
+
+ public CramerShoupKeyGenerationParameters(SecureRandom random, CramerShoupParameters params) {
+ super(random, getStrength(params));
+
+ this.params = params;
+ }
+
+ public CramerShoupParameters getParameters() {
+ return params;
+ }
+
+ static int getStrength(CramerShoupParameters params) {
+ return params.getP().bitLength();
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java
new file mode 100644
index 00000000..9e4219c8
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java
@@ -0,0 +1,40 @@
+package org.bouncycastle.crypto.params;
+
+public class CramerShoupKeyParameters extends AsymmetricKeyParameter {
+
+ private CramerShoupParameters params;
+
+ protected CramerShoupKeyParameters(boolean isPrivate, CramerShoupParameters params) {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public CramerShoupParameters getParameters() {
+ return params;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CramerShoupKeyParameters)) {
+ return false;
+ }
+
+ CramerShoupKeyParameters csKey = (CramerShoupKeyParameters) obj;
+
+ if (params == null) {
+ return csKey.getParameters() == null;
+ } else {
+ return params.equals(csKey.getParameters());
+ }
+ }
+
+ public int hashCode() {
+ int code = isPrivate() ? 0 : 1;
+
+ if (params != null) {
+ code ^= params.hashCode();
+ }
+
+ return code;
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java
new file mode 100644
index 00000000..24264b6c
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Digest;
+
+public class CramerShoupParameters implements CipherParameters {
+
+ private BigInteger p; // prime order of G
+ private BigInteger g1, g2; // generate G
+
+ private Digest H; // hash function
+
+ public CramerShoupParameters(BigInteger p, BigInteger g1, BigInteger g2, Digest H) {
+ this.p = p;
+ this.g1 = g1;
+ this.g2 = g2;
+ this.H = H;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DSAParameters)) {
+ return false;
+ }
+
+ CramerShoupParameters pm = (CramerShoupParameters) obj;
+
+ return (pm.getP().equals(p) && pm.getG1().equals(g1) && pm.getG2().equals(g2));
+ }
+
+ public int hashCode() {
+ return getP().hashCode() ^ getG1().hashCode() ^ getG2().hashCode();
+ }
+
+ public BigInteger getG1() {
+ return g1;
+ }
+
+ public BigInteger getG2() {
+ return g2;
+ }
+
+ public BigInteger getP() {
+ return p;
+ }
+
+ public Digest getH() {
+ H.reset();
+ return H;
+ }
+
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java
new file mode 100644
index 00000000..79de46ad
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java
@@ -0,0 +1,61 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class CramerShoupPrivateKeyParameters extends CramerShoupKeyParameters {
+
+ private BigInteger x1, x2, y1, y2, z; // Z_p
+ private CramerShoupPublicKeyParameters pk; // public key
+
+ public CramerShoupPrivateKeyParameters(CramerShoupParameters params, BigInteger x1, BigInteger x2, BigInteger y1, BigInteger y2, BigInteger z) {
+ super(true, params);
+
+ this.x1 = x1;
+ this.x2 = x2;
+ this.y1 = y1;
+ this.y2 = y2;
+ this.z = z;
+ }
+
+ public BigInteger getX1() {
+ return x1;
+ }
+
+ public BigInteger getX2() {
+ return x2;
+ }
+
+ public BigInteger getY1() {
+ return y1;
+ }
+
+ public BigInteger getY2() {
+ return y2;
+ }
+
+ public BigInteger getZ() {
+ return z;
+ }
+
+ public void setPk(CramerShoupPublicKeyParameters pk) {
+ this.pk = pk;
+ }
+
+ public CramerShoupPublicKeyParameters getPk() {
+ return pk;
+ }
+
+ public int hashCode() {
+ return x1.hashCode() ^ x2.hashCode() ^ y1.hashCode() ^ y2.hashCode() ^ z.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CramerShoupPrivateKeyParameters)) {
+ return false;
+ }
+
+ CramerShoupPrivateKeyParameters other = (CramerShoupPrivateKeyParameters) obj;
+
+ return other.getX1().equals(this.x1) && other.getX2().equals(this.x2) && other.getY1().equals(this.y1) && other.getY2().equals(this.y2) && other.getZ().equals(this.z) && super.equals(obj);
+ }
+}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java
new file mode 100644
index 00000000..341149c1
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java
@@ -0,0 +1,42 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class CramerShoupPublicKeyParameters extends CramerShoupKeyParameters {
+
+ private BigInteger c, d, h; // public key group elements
+
+ public CramerShoupPublicKeyParameters(CramerShoupParameters params, BigInteger c, BigInteger d, BigInteger h) {
+ super(false, params);
+
+ this.c = c;
+ this.d = d;
+ this.h = h;
+ }
+
+ public BigInteger getC() {
+ return c;
+ }
+
+ public BigInteger getD() {
+ return d;
+ }
+
+ public BigInteger getH() {
+ return h;
+ }
+
+ public int hashCode() {
+ return c.hashCode() ^ d.hashCode() ^ h.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CramerShoupPublicKeyParameters)) {
+ return false;
+ }
+
+ CramerShoupPublicKeyParameters other = (CramerShoupPublicKeyParameters) obj;
+
+ return other.getC().equals(c) && other.getD().equals(d) && other.getH().equals(h) && super.equals(obj);
+ }
+}