2
$\begingroup$

I have a case where to ensure the same encrypted string for the given input. Say for example If "Hello" is encrypted more than one time then same encrypted string should be i should get as an output (Like in hash algorithms). I have tried pure "ECIES" & "ElGamal" algorithms using bouncycastle but both returns different outputs each time for the same input.

I have tried with RSA by setting the "RSA/ECB/NoPadding" option and it works like charm. But RSA is both performance and memory consuming stuff so i choosen the Eliptic curve which will us both performance and efficient memory. So I choose ECIES initially and also "Elgamal".

What should i set for ECIES and ElGamal to produce same output each time for same input.?

public class AsymmetricElGamalCipher extends BaseAsymmetricCipher {

private final SecureRandom random;

public AsymmetricElGamalCipher(final Config config) throws AndesException {
    super(CryptAlgorithmType.ELGAMAL, config);
    this.random = KeyPairUtils.createFixedRandom();
}

/**
 * Encrypt the given bytes of data using the ECC public key
 *
 * @param value
 *            The data to be encoded or encrypted
 * @return The encrypted/encoded data
 * @throws AndesException
 *             if an error occurred during the operation
 */
public byte[] encrypt(byte[] value) throws AndesException {
    byte[] hexEncodedCipher = null;
     try {
         this.cipher.init(Cipher.ENCRYPT_MODE, this.publicKey, this.random);
        hexEncodedCipher = this.cipher.doFinal(value);
     } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new AndesException(e);
     }
     return hexEncodedCipher;
}

/**
 * Encrypt the given plain text using the Elgamal private key
 *
 * @param cipherText
 *            The data to be decoded/decrypted
 * @return The decrypted/decoded bytes of data
 * @throws AndesException
 *             if an error occurred during the operation
 */
public byte[] decrypt(byte[] value)  throws AndesException {
    byte[] hexEncodedCipher = null;
    try {
        this.cipher.init(Cipher.DECRYPT_MODE, this.privateKey, this.random);
        hexEncodedCipher = this.cipher.doFinal(value);
    } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
        throw new AndesException(e);
 }
    return hexEncodedCipher;
}

}

Here is the Ecc algorithm code,

public class AsymmetricEccCipher extends BaseAsymmetricCipher {

 //  generate derivation and encoding vectors
private final byte[]  d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
private final byte[]  e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
private final String initVector = "0000000000000000";
private final IESParameterSpec ALGORITHM_PARAMETER_SPEC;

public AsymmetricEccCipher(final Config config) throws AndesException {
    super(CryptAlgorithmType.ECIES, config);
    try {
        ALGORITHM_PARAMETER_SPEC = new IESParameterSpec(d, e, 128, 128, this.initVector.getBytes(IAndes.CHARACTER_TYPE_UTF_8), true);
    } catch (UnsupportedEncodingException e) {
        throw new AndesException("EC IES parameter spec creation error.");
    }
}

/**
 * Encrypt the given bytes of data using the ECC public key
 *
 * @param value
 *            The data to be encoded or encrypted
 * @return The encrypted/encoded data
 * @throws AndesException
 *             if an error occurred during the operation
 */
public byte[] encrypt(byte[] value) throws AndesException {
    byte[] hexEncodedCipher = null;
     try {
         this.cipher.init(Cipher.ENCRYPT_MODE, this.publicKey, this.ALGORITHM_PARAMETER_SPEC);
        hexEncodedCipher = this.cipher.doFinal(value);
     } catch (InvalidKeyException | IllegalBlockSizeException
                | BadPaddingException | InvalidAlgorithmParameterException e) {
            throw new AndesException(e);
     }
     return hexEncodedCipher;
}

/**
 * Encrypt the given plain text using the ECC private key
 *
 * @param cipherText
 *            The data to be decoded/decrypted
 * @return The decrypted/decoded bytes of data
 * @throws AndesException
 *             if an error occurred during the operation
 */
public byte[] decrypt(byte[] value)  throws AndesException {
    byte[] hexEncodedCipher = null;
    try {
        this.cipher.init(Cipher.DECRYPT_MODE, this.privateKey, this.ALGORITHM_PARAMETER_SPEC);
        hexEncodedCipher = this.cipher.doFinal(value);
    } catch (InvalidKeyException | IllegalBlockSizeException
            | BadPaddingException | InvalidAlgorithmParameterException e) {
        throw new AndesException(e);
    }
    return hexEncodedCipher;
}

}

$\endgroup$
  • $\begingroup$ Kind of obvious: but you can try to replace the random number generator to return a deterministic value, either by replacing the RNG (but this is dangerous as the retrieval of random data may change between versions) or by refactoring the code: removing the RNG for e.g. a hash over the message (supplied with the ciphertext) or anything else that is deterministic. Obviously you would not be talking about ECIES or ElGamal if you do, it would be dangerous to do so. $\endgroup$ – Maarten Bodewes Mar 1 '17 at 22:13
  • $\begingroup$ Using ElGamal in a deterministic way means the assumptions in the security proof are not met... best case: you're lucky and nothing bad happens, worst case: as "secure" as sending the message in plaintext. Also, using RSA in ECB mode without padding is quite bad with respect to security. If you need a deterministic encryption scheme, then use one which is made for that kind of usage. $\endgroup$ – tylo May 31 '17 at 8:29
  • $\begingroup$ You should not do this since you are loosing semantic security... However, I think you can easily do it in your bouncy castle code by simply seeding the SecureRandom used by the cipher. If it doesn't work, please show us your code, that would make it easier to explain. $\endgroup$ – Lery Jul 30 '17 at 20:09
  • $\begingroup$ I have tried with SecureRandom (constant random number value) but got different encrypted values for same input multiple times. I have edited my post with sample code. $\endgroup$ – Hakuna Matata Aug 2 '17 at 6:29
1
$\begingroup$

These public key algorithms are designed with this sort of randomness as part of their security model, to stop leakage of information of the sort you seem to want as a feature.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Yes. I understood that one. But there are cases you wont need that randomness. $\endgroup$ – Hakuna Matata Mar 1 '17 at 21:13
  • $\begingroup$ See the answer and discussion at this question: crypto.stackexchange.com/questions/24328/… Maybe blinding on the second pair of keys where the second public key is kept secret may work. $\endgroup$ – kodlu Mar 1 '17 at 21:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.