运行测试时出现密码初始化错误

时间:2014-10-01 16:07:52

标签: java encryption

我写了一个实用程序,使用AES算法进行加密和解密。常规程序工作正常,但是当我使用相同的方法运行测试时,我在doFinal方法上得到了Cipher初始化错误。

我做了一些研究,有些人建议将initdoFinal放在同步块中。我这样做了,仍然得到同样的例外。

我还根据某个论坛的建议更新了US_export_policy.jar文件夹中的local_policy.jarjre7/lib/security。仍然有同样的问题。

代码中可能出现什么问题?

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.log4j.Logger;

public class CipherUtil {
    private static Logger log = Logger.getLogger(CipherUtil.class);
    private static final String SECRET_KEY = "000102030405060708090A0B0C0D0E0F";
    private Cipher cipher;
    private SecretKeySpec secretKeySpec;

    private static CipherUtil cipherUtil;

    private CipherUtil() {
        try {
            cipher = Cipher.getInstance("AES");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {
            log.error(ex);
        }
        byte[] key = null;
        try {
            key = Hex.decodeHex(SECRET_KEY.toCharArray());
        } catch (DecoderException ex) {
            log.error(ex);
        }
        secretKeySpec = new SecretKeySpec(key, "AES");
    }

    public static synchronized CipherUtil getCipherUtilObject() {
        if (cipherUtil == null) {
            cipherUtil = new CipherUtil();
        }
        return cipherUtil;
    }

    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    public String encrypt(String plainText) {
        if (plainText == null)
            return null;
        String encryptedText = null;
        byte[] encrypted = null;

        synchronized (cipher) {
            try {
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            } catch (InvalidKeyException e) {
                log.error(e.getMessage());
            }
        }

        synchronized (cipher) {
            try {
                encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
                encryptedText = new String(Base64.encodeBase64(encrypted));
            } catch (IllegalBlockSizeException | BadPaddingException
                    | UnsupportedEncodingException e) {
                log.error(e.getMessage());
            }
        }

        return encryptedText;
    }

    public synchronized String decrypt(String encryptedText) {
        if (encryptedText == null)
            return null;
        byte[] toDecrypt = null;
        byte[] original = null;
        String decryptedText = null;

        synchronized (cipher) {
            try {
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            } catch (InvalidKeyException e) {
                log.error(e.getMessage());
            }
        }
        toDecrypt = Base64.decodeBase64(encryptedText);
        synchronized (cipher) {
            try {
                original = cipher.doFinal(toDecrypt);
            } catch (IllegalBlockSizeException | BadPaddingException e) {
                log.error(e.getMessage());
            }
        }
        try {
            decryptedText = new String(original, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());
        }

        return decryptedText;
    }
}

和测试类:

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;

import org.junit.Before;
import org.junit.Test;

public class CipherTest {
    CipherUtil cipherUtil;

    @Before
    public void setUp() {
        cipherUtil = CipherUtil.getCipherUtilObject();
    }

    @Test
    public void testEncryptDecrypt() {
        String plainText = "Secret Message";
        String encryptedText = cipherUtil.encrypt(plainText);
        assertThat(encryptedText, not(equalTo(plainText)));
        String decryptedText = cipherUtil.decrypt(encryptedText);
        assertThat(decryptedText, is(equalTo(plainText)));
        assertThat(encryptedText, not(equalTo(decryptedText)));
    }
}

最后这是例外:

java.lang.IllegalStateException: Cipher not initialized
    at javax.crypto.Cipher.checkCipherState(Cipher.java:1672)
    at javax.crypto.Cipher.doFinal(Cipher.java:2079)
    at com.testapp.util.CipherUtil.encrypt(CipherUtil.java:67)
    at com.testapp.util.CipherTest.testEncryptDecrypt(CipherTest.java:23)

1 个答案:

答案 0 :(得分:1)

我的机器上的代码运行正常。请注意,您的encrypt方法未同步,因此在线程环境中运行此方法会使其失败。通常,每个线程应该有一个Cipher实例。 Cipher在方法调用之间包含状态,因此只是同步访问方法调用本身也会不时失败。