Created
March 23, 2013 08:32
OperSSL 加密和解密的Java实现
大牛给的实现 :http://stackoverflow.com/questions/11783062/how-to-decrypt-an-encrypted-file-in-java-with-openssl-with-aes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cn.is.ftp; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.security.InvalidKeyException; | |
import java.security.MessageDigest; | |
import java.security.NoSuchAlgorithmException; | |
import javax.crypto.BadPaddingException; | |
import javax.crypto.Cipher; | |
import javax.crypto.IllegalBlockSizeException; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.SecretKeySpec; | |
/** | |
* Class created for StackOverflow by owlstead. This is open source, you are free to copy and use for any purpose. | |
*/ | |
public class OpenSSLDecryptor { | |
private static final int INDEX_KEY = 0; | |
private static final int INDEX_IV = 1; | |
private static final int ITERATIONS = 1; | |
private static final int KEY_SIZE_BITS = 128; | |
/** | |
* Thanks go to Ola Bini for releasing this source on his blog. The source was obtained from <a | |
* href="http://olabini.com/blog/tag/evp_bytestokey/">here</a> . | |
*/ | |
public static byte[][] EVP_BytesToKey(int key_len, int iv_len, MessageDigest md, byte[] salt, byte[] data, int count) { | |
byte[][] both = new byte[2][]; | |
byte[] key = new byte[key_len]; | |
int key_ix = 0; | |
byte[] iv = new byte[iv_len]; | |
int iv_ix = 0; | |
both[0] = key; | |
both[1] = iv; | |
byte[] md_buf = null; | |
int nkey = key_len; | |
int niv = iv_len; | |
int i = 0; | |
if (data == null) { | |
return both; | |
} | |
int addmd = 0; | |
for (;;) { | |
md.reset(); | |
if (addmd++ > 0) { | |
md.update(md_buf); | |
} | |
md.update(data); | |
if (null != salt) { | |
md.update(salt, 0, 8); | |
} | |
md_buf = md.digest(); | |
for (i = 1; i < count; i++) { | |
md.reset(); | |
md.update(md_buf); | |
md_buf = md.digest(); | |
} | |
i = 0; | |
if (nkey > 0) { | |
for (;;) { | |
if (nkey == 0) | |
break; | |
if (i == md_buf.length) | |
break; | |
key[key_ix++] = md_buf[i]; | |
nkey--; | |
i++; | |
} | |
} | |
if (niv > 0 && i != md_buf.length) { | |
for (;;) { | |
if (niv == 0) | |
break; | |
if (i == md_buf.length) | |
break; | |
iv[iv_ix++] = md_buf[i]; | |
niv--; | |
i++; | |
} | |
} | |
if (nkey == 0 && niv == 0) { | |
break; | |
} | |
} | |
for (i = 0; i < md_buf.length; i++) { | |
md_buf[i] = 0; | |
} | |
return both; | |
} | |
public static byte[] encrypt(byte[] salt, byte[] contents, String pw) throws NoSuchAlgorithmException, NoSuchPaddingException, | |
InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { | |
Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
MessageDigest md5 = MessageDigest.getInstance("MD5"); | |
final byte[][] keyAndIV = EVP_BytesToKey(KEY_SIZE_BITS / Byte.SIZE, aesCBC.getBlockSize(), md5, salt, pw.getBytes(), ITERATIONS); | |
SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES"); | |
IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]); | |
aesCBC.init(Cipher.ENCRYPT_MODE, key, iv); | |
return aesCBC.doFinal(contents); | |
} | |
public static byte[] decrypt(byte[] salt, byte[] encrypted, String pw) throws NoSuchAlgorithmException, NoSuchPaddingException, | |
InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { | |
Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
MessageDigest md5 = MessageDigest.getInstance("MD5"); | |
final byte[][] keyAndIV = EVP_BytesToKey(KEY_SIZE_BITS / Byte.SIZE, aesCBC.getBlockSize(), md5, salt, pw.getBytes(), ITERATIONS); | |
SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES"); | |
IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]); | |
aesCBC.init(Cipher.DECRYPT_MODE, key, iv); | |
return aesCBC.doFinal(encrypted); | |
} | |
public static void main(String[] args) throws Exception { | |
String pw = "AKeyForAES128CBC"; | |
byte[] salt = "1234567890".getBytes(); | |
byte[] encrypted = "Secret message! Oh, My GOD!".getBytes(); | |
byte[] decrypted = encrypt(salt, encrypted, pw); | |
String str = Base16.encode(decrypted); | |
System.out.println(str); | |
String answer = new String(decrypt(salt, decrypted, pw)); | |
System.out.println(answer); | |
answer = new String(decrypt(salt, Base16.decode(str), pw)); | |
System.out.println(answer); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment