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
path: root/core/src
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2014-06-27 04:54:10 +0400
committerDavid Hook <dgh@cryptoworkshop.com>2014-06-27 04:54:10 +0400
commit1dcd73f5fa7df235ef2f863391d20f587286b52e (patch)
tree235a79159551ae0f92ff866f3be9d557117af9bc /core/src
parent144d6dbf2df00d3fd98f46838b040b215a995c72 (diff)
1.4 fixes.
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java325
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java523
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java225
3 files changed, 578 insertions, 495 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
index 1e43eb2a..0d8ba19d 100644
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java
+++ b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java
@@ -3,160 +3,177 @@ 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;
- }
+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;
+ }
+
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ 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
index cc6d96be..5fcfff9b 100644
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java
+++ b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java
@@ -13,263 +13,302 @@ 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 {
+public class CramerShoupCoreEngine
+{
- private static final BigInteger ONE = BigInteger.ONE;
-
- private CramerShoupKeyParameters key;
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private CramerShoupKeyParameters key;
private SecureRandom random;
- private boolean forEncryption;
- private String label = null;
-
- /**
- * initialise the CramerShoup engine.
- *
- * @param forEncryption
- * 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 forEncryption, CipherParameters param, String label) {
- init(forEncryption, param);
-
- this.label = label;
- }
-
- /**
- * initialise the CramerShoup engine.
- *
- * @param forEncryption
- * whether this engine should encrypt or decrypt
- * @param param
- * the necessary CramerShoup key parameters.
- */
- public void init(boolean forEncryption, CipherParameters param) {
+ private boolean forEncryption;
+ private String label = null;
+
+ /**
+ * initialise the CramerShoup engine.
+ *
+ * @param forEncryption 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 forEncryption, CipherParameters param, String label)
+ {
+ init(forEncryption, param);
+
+ this.label = label;
+ }
+
+ /**
+ * initialise the CramerShoup engine.
+ *
+ * @param forEncryption whether this engine should encrypt or decrypt
+ * @param param the necessary CramerShoup key parameters.
+ */
+ public void init(boolean forEncryption, CipherParameters param)
+ {
SecureRandom providedRandom = null;
- if (param instanceof ParametersWithRandom) {
- ParametersWithRandom rParam = (ParametersWithRandom) param;
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
- key = (CramerShoupKeyParameters) rParam.getParameters();
+ key = (CramerShoupKeyParameters)rParam.getParameters();
providedRandom = rParam.getRandom();
- } else {
- key = (CramerShoupKeyParameters) param;
- }
+ }
+ else
+ {
+ key = (CramerShoupKeyParameters)param;
+ }
this.random = initSecureRandom(forEncryption, providedRandom);
- this.forEncryption = forEncryption;
- }
-
- /**
- * 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, random);
-
- 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;
- }
+ this.forEncryption = forEncryption;
+ }
+
+ /**
+ * 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.
+ * <p/>
+ * 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.
+ * <p/>
+ * 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, random);
+
+ 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;
+ }
protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
{
return !needed ? null : (provided != null) ? provided : new SecureRandom();
}
- /**
- * CS exception for wrong cipher-texts
- */
- public class CramerShoupCiphertextException extends Exception {
-
- private static final long serialVersionUID = -6360977166495345076L;
-
- public CramerShoupCiphertextException(String msg) {
- super(msg);
- }
-
- }
+ /**
+ * 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/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java
index 2eb90152..e9633572 100644
--- a/core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java
+++ b/core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java
@@ -15,106 +15,133 @@ import org.bouncycastle.crypto.params.CramerShoupParameters;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.test.SimpleTest;
-public class CramerShoupTest extends SimpleTest {
+public class CramerShoupTest
+ extends SimpleTest
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
private static final SecureRandom RND = new SecureRandom();
- private AsymmetricCipherKeyPair keyPair;
-
- public static void main(String[] args) {
- runTest(new CramerShoupTest());
- }
-
- @Override
- public String getName() {
- return "CramerShoup";
- }
-
- @Override
- public void performTest() throws Exception {
- BigInteger pSubOne = DHStandardGroups.rfc3526_2048.getP().subtract(BigInteger.ONE);
- for (int i = 0; i < 10; ++i) {
- BigInteger message = BigIntegers.createRandomInRange(BigInteger.ONE, pSubOne, RND);
-
- BigInteger m1 = encDecTest(message);
- BigInteger m2 = labelledEncDecTest(message, "myRandomLabel");
- BigInteger m3 = encDecEncodingTest(message);
- BigInteger m4 = labelledEncDecEncodingTest(message, "myOtherCoolLabel");
-
- if (!message.equals(m1) || !message.equals(m2) || !message.equals(m3) || !message.equals(m4)){
- fail("decrypted message != original message");
- }
- }
- }
-
- private BigInteger encDecEncodingTest(BigInteger m){
- CramerShoupCiphertext ciphertext = encrypt(m);
- byte[] c = ciphertext.toByteArray();
- CramerShoupCiphertext decC = new CramerShoupCiphertext(c);
- return decrypt(decC);
- }
-
- private BigInteger labelledEncDecEncodingTest(BigInteger m, String l){
- byte[] c = encrypt(m, l).toByteArray();
- return decrypt(new CramerShoupCiphertext(c), l);
- }
-
- private BigInteger encDecTest(BigInteger m){
- CramerShoupCiphertext c = encrypt(m);
- return decrypt(c);
- }
-
- private BigInteger labelledEncDecTest(BigInteger m, String l){
- CramerShoupCiphertext c = encrypt(m, l);
- return decrypt(c, l);
- }
-
-
- private BigInteger decrypt(CramerShoupCiphertext ciphertext) {
- return decrypt(ciphertext, null);
- }
-
- private BigInteger decrypt(CramerShoupCiphertext ciphertext, String label) {
-
- CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
- if (label != null)
- engine.init(false, keyPair.getPrivate(), label);
- else
- engine.init(false, keyPair.getPrivate());
- try {
- BigInteger m = engine.decryptBlock(ciphertext);
-
- return m;
- } catch (CramerShoupCiphertextException e) {
- e.printStackTrace();
- }
-
- return null;
- }
-
- private CramerShoupCiphertext encrypt(BigInteger message) {
- return encrypt(message, null);
- }
-
- private CramerShoupCiphertext encrypt(BigInteger message, String label) {
- CramerShoupKeyPairGenerator kpGen = new CramerShoupKeyPairGenerator();
- CramerShoupParametersGenerator pGen = new CramerShoupParametersGenerator();
-
- pGen.init(2048, 1, RND);
- CramerShoupParameters params = pGen.generateParameters(DHStandardGroups.rfc3526_2048);
- CramerShoupKeyGenerationParameters param = new CramerShoupKeyGenerationParameters(RND, params);
-
- kpGen.init(param);
- keyPair = kpGen.generateKeyPair();
-
- CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
- if (label != null)
- engine.init(true, keyPair.getPublic(), label);
- else
- engine.init(true, keyPair.getPublic());
-
- CramerShoupCiphertext ciphertext = engine.encryptBlock(message);
-
- return ciphertext;
- }
+ private AsymmetricCipherKeyPair keyPair;
+
+ public static void main(String[] args)
+ {
+ runTest(new CramerShoupTest());
+ }
+
+ public String getName()
+ {
+ return "CramerShoup";
+ }
+
+
+ public void performTest()
+ throws Exception
+ {
+ BigInteger pSubOne = DHStandardGroups.rfc3526_2048.getP().subtract(ONE);
+ for (int i = 0; i < 10; ++i)
+ {
+ BigInteger message = BigIntegers.createRandomInRange(ONE, pSubOne, RND);
+
+ BigInteger m1 = encDecTest(message);
+ BigInteger m2 = labelledEncDecTest(message, "myRandomLabel");
+ BigInteger m3 = encDecEncodingTest(message);
+ BigInteger m4 = labelledEncDecEncodingTest(message, "myOtherCoolLabel");
+
+ if (!message.equals(m1) || !message.equals(m2) || !message.equals(m3) || !message.equals(m4))
+ {
+ fail("decrypted message != original message");
+ }
+ }
+ }
+
+ private BigInteger encDecEncodingTest(BigInteger m)
+ {
+ CramerShoupCiphertext ciphertext = encrypt(m);
+ byte[] c = ciphertext.toByteArray();
+ CramerShoupCiphertext decC = new CramerShoupCiphertext(c);
+ return decrypt(decC);
+ }
+
+ private BigInteger labelledEncDecEncodingTest(BigInteger m, String l)
+ {
+ byte[] c = encrypt(m, l).toByteArray();
+ return decrypt(new CramerShoupCiphertext(c), l);
+ }
+
+ private BigInteger encDecTest(BigInteger m)
+ {
+ CramerShoupCiphertext c = encrypt(m);
+ return decrypt(c);
+ }
+
+ private BigInteger labelledEncDecTest(BigInteger m, String l)
+ {
+ CramerShoupCiphertext c = encrypt(m, l);
+ return decrypt(c, l);
+ }
+
+
+ private BigInteger decrypt(CramerShoupCiphertext ciphertext)
+ {
+ return decrypt(ciphertext, null);
+ }
+
+ private BigInteger decrypt(CramerShoupCiphertext ciphertext, String label)
+ {
+
+ CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
+ if (label != null)
+ {
+ engine.init(false, keyPair.getPrivate(), label);
+ }
+ else
+ {
+ engine.init(false, keyPair.getPrivate());
+ }
+ try
+ {
+ BigInteger m = engine.decryptBlock(ciphertext);
+
+ return m;
+ }
+ catch (CramerShoupCiphertextException e)
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private CramerShoupCiphertext encrypt(BigInteger message)
+ {
+ return encrypt(message, null);
+ }
+
+ private CramerShoupCiphertext encrypt(BigInteger message, String label)
+ {
+ CramerShoupKeyPairGenerator kpGen = new CramerShoupKeyPairGenerator();
+ CramerShoupParametersGenerator pGen = new CramerShoupParametersGenerator();
+
+ pGen.init(2048, 1, RND);
+ CramerShoupParameters params = pGen.generateParameters(DHStandardGroups.rfc3526_2048);
+ CramerShoupKeyGenerationParameters param = new CramerShoupKeyGenerationParameters(RND, params);
+
+ kpGen.init(param);
+ keyPair = kpGen.generateKeyPair();
+
+ CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
+ if (label != null)
+ {
+ engine.init(true, keyPair.getPublic(), label);
+ }
+ else
+ {
+ engine.init(true, keyPair.getPublic());
+ }
+
+ CramerShoupCiphertext ciphertext = engine.encryptBlock(message);
+
+ return ciphertext;
+ }
}