diff options
author | David Hook <dgh@cryptoworkshop.com> | 2014-06-27 04:54:10 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2014-06-27 04:54:10 +0400 |
commit | 1dcd73f5fa7df235ef2f863391d20f587286b52e (patch) | |
tree | 235a79159551ae0f92ff866f3be9d557117af9bc /core/src/main/java/org/bouncycastle | |
parent | 144d6dbf2df00d3fd98f46838b040b215a995c72 (diff) |
1.4 fixes.
Diffstat (limited to 'core/src/main/java/org/bouncycastle')
-rw-r--r-- | core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java | 325 | ||||
-rw-r--r-- | core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java | 523 |
2 files changed, 452 insertions, 396 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); + } + + } } |