1)明文变密文(你不知道密钥是很难解密的);
2)数据的一致性(hash值一样);
3)数据的可信任性(验签)。
2. 两种不同的加密与解密
1)对称加密:加密与解密使用相同的密钥,处理速度快;
2)非对称加密:加密与解密使用不同的密钥(生对生成),处理速度不及对称加密。
3.在非对称加密中,究竟是公钥加密还是私钥加密的问题
1)如果只是用加密的用途
公钥加密,私钥解密(私钥只有一个,公钥大家都知道)。
2)如果用验签
私钥加密,公钥解密(解密的来源是私钥,其它的来源是不可信任的)。
下面是两个工具类。
import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.Cipher; public class RSAHelper { public static final String KEY_ALGORITHM = "RSA"; private static final int KEY_LENGTH = 1024; public static final String PUBLIC_KEY = "PublicKey"; public static final String PRIVATE_KEY = "PrivateKey"; private static final int MAX_ENCRYPT_BLOCK = 117; private static final int MAX_DECRYPT_BLOCK = 128; private static final String SIGNATURE_ALGORITHM = "MD5withRSA"; public RSAHelper() { } public static void generateKeyPair(Map<String, Object> keyMap) { boolean result = false; KeyPairGenerator keyPairGenerator = null; try { keyPairGenerator = KeyPairGenerator.getInstance("RSA"); result = true; } catch (NoSuchAlgorithmException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } if (result) { SecureRandom secureRandom = new SecureRandom(); String currentDateTime = new SimpleDateFormat("yyyyMMddHHmmssSSS") .format(new Date()); secureRandom.setSeed(currentDateTime.getBytes()); keyPairGenerator.initialize(1024, secureRandom); KeyPair keyPair = keyPairGenerator.genKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); keyMap.put("PublicKey", publicKey.getEncoded()); keyMap.put("PrivateKey", privateKey.getEncoded()); } } public static void saveKeyPair(Map<String, Object> keyPair, String publicKeyFileName, String privateKeyFileName) { try { FileOutputStream fileOutputStream = new FileOutputStream( publicKeyFileName); byte[] publicKey = (byte[]) keyPair.get("PublicKey"); fileOutputStream.write(publicKey); fileOutputStream.close(); } catch (FileNotFoundException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } try { FileOutputStream fileOutputStream = new FileOutputStream( privateKeyFileName); byte[] privateKey = (byte[]) keyPair.get("PrivateKey"); fileOutputStream.write(privateKey); fileOutputStream.close(); } catch (FileNotFoundException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } } public static byte[] getKey(String keyFileName) { byte[] keyBytes = null; try { File file = new File(keyFileName); FileInputStream fileInputStream = new FileInputStream(file); DataInputStream dataInputStream = new DataInputStream( fileInputStream); keyBytes = new byte[(int) file.length()]; dataInputStream.readFully(keyBytes); dataInputStream.close(); fileInputStream.close(); } catch (FileNotFoundException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } return keyBytes; } public static byte[] encryptWithPublicKey(byte[] data, int offSet, int length, byte[] keyBytes) throws Exception { X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(1, publicK); ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; while (length - offSet > 0) { byte[] cache; if (length - offSet > 117) { cache = cipher.doFinal(data, offSet, 117); } else { cache = cipher.doFinal(data, offSet, length - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 117; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } public static byte[] encryptWithPrivateKey(byte[] data, int offSet, int length, byte[] keyBytes) throws Exception { PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(1, privateK); ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; while (length - offSet > 0) { byte[] cache; if (length - offSet > 117) { cache = cipher.doFinal(data, offSet, 117); } else { cache = cipher.doFinal(data, offSet, length - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 117; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } public static byte[] decryptWithPublicKey(byte[] data, int offSet, int length, byte[] keyBytes) throws Exception { X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(2, publicK); ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; while (length - offSet > 0) { byte[] cache; if (length - offSet > 128) { cache = cipher.doFinal(data, offSet, 128); } else { cache = cipher.doFinal(data, offSet, length - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 128; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } public static byte[] decryptWithPrivateKey(byte[] data, int offSet, int length, byte[] keyBytes) throws Exception { PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(2, privateK); ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; while (length - offSet > 0) { byte[] cache; if (length - offSet > 128) { cache = cipher.doFinal(data, offSet, 128); } else { cache = cipher.doFinal(data, offSet, length - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 128; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } public static byte[] sign(byte[] data, int offset, int length, byte[] privateKeyBytes) { byte[] signedData = null; try { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec( privateKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory .generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("MD5withRSA"); signature.initSign(privateKey); signature.update(data, offset, length); signedData = signature.sign(); } catch (Exception ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } return signedData; } public static boolean verify(byte[] data, int offset, int length, byte[] publicKeyBytes, byte[] dataSignature) { boolean result = false; try { X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec( publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Signature signature = Signature.getInstance("MD5withRSA"); signature.initVerify(publicKey); signature.update(data, offset, length); result = signature.verify(dataSignature); } catch (Exception ex) { Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null, ex); } return result; } }
import com.adph.jms.Base64Utils; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; public class RSAKeyUtils { private static String RAS_PUBLICKEY_PATH = "D://security.key"; private static String RSA_PRIVATEKEY_PATH= "D://security.crt"; public RSAKeyUtils() { } protected static void init(String RAS_PUBLICKEY_PATH, String RSA_PRIVATEKEY_PATH) { try { FileUtils.forceMkdir(new File(new File(RAS_PUBLICKEY_PATH) .getParent())); Map<String, Object> keyPair = new HashMap(); RSAHelper.generateKeyPair(keyPair); RSAHelper.saveKeyPair(keyPair, RAS_PUBLICKEY_PATH, RSA_PRIVATEKEY_PATH); } catch (IOException e) { e.printStackTrace(); } } public static void setKeyPath(String keyPath) { RAS_PUBLICKEY_PATH = keyPath; } public static void setCrtPath(String crtPath) { RSA_PRIVATEKEY_PATH = crtPath; } public static String encByPublicKey(String data) { String dataBack = ""; try { if (!StringUtils.isEmpty(data)) { byte[] Bytes = RSAHelper.encryptWithPublicKey(data.getBytes(), 0, data.getBytes().length, RSAHelper.getKey(RAS_PUBLICKEY_PATH)); dataBack = Base64Utils.encode(Bytes); } } catch (Exception e) { e.printStackTrace(); } return dataBack; } public static String encByPrivateKey(String data) { String dataBack = ""; try { if (!StringUtils.isEmpty(data)) { byte[] Bytes = RSAHelper.encryptWithPrivateKey(data.getBytes(), 0, data.getBytes().length, RSAHelper.getKey(RSA_PRIVATEKEY_PATH)); dataBack = Base64Utils.encode(Bytes); } } catch (Exception e) { e.printStackTrace(); } return dataBack; } public static String decByPublicKey(String data) { String dataBack = ""; try { if (!StringUtils.isEmpty(data)) { byte[] Bytes = RSAHelper.decryptWithPublicKey( Base64Utils.decode(data), 0, Base64Utils.decode(data).length, RSAHelper.getKey(RAS_PUBLICKEY_PATH)); dataBack = new String(Bytes); } } catch (Exception e) { e.printStackTrace(); } return dataBack; } public static String decByPrivateKey(String data) { String dataBack = ""; try { if (!StringUtils.isEmpty(data)) { byte[] Bytes = RSAHelper.decryptWithPrivateKey( Base64Utils.decode(data), 0, Base64Utils.decode(data).length, RSAHelper.getKey(RSA_PRIVATEKEY_PATH)); dataBack = new String(Bytes); } } catch (Exception e) { e.printStackTrace(); } return dataBack; } public static String doSignPrivateKey(String data) { String dataBack = ""; try { if (!StringUtils.isEmpty(data)) { byte[] Bytes = RSAHelper.sign(data.getBytes(), 0, data.getBytes().length, RSAHelper.getKey(RSA_PRIVATEKEY_PATH)); dataBack = Base64Utils.encode(Bytes); } } catch (Exception e) { e.printStackTrace(); } return dataBack; } public static boolean doVerifyPublicKey(String data, String sign) { Boolean returnFlag = Boolean.FALSE; if ((StringUtils.isEmpty(data)) || (StringUtils.isEmpty(sign))) { return Boolean.FALSE.booleanValue(); } try { returnFlag = Boolean.valueOf(RSAHelper.verify(data.getBytes(), 0, data.getBytes().length, RSAHelper.getKey(RAS_PUBLICKEY_PATH), Base64Utils.decode(sign))); } catch (Exception e) { e.printStackTrace(); } return returnFlag.booleanValue(); } // public static void main(String[] args) { // init("D://security.key", "D://security.crt"); // } }
写一个例子测试下。 注意:先要运行上面main方法,使其生成security.key和security.crt。
public class EncTest { public static void main(String[] args) throws Exception { String text = "Hello World"; String enc = RSAKeyUtils.encByPublicKey(text); System.out.println("加密数据:" + enc); System.out.println("解密数据:" + RSAKeyUtils.decByPrivateKey(enc)); String sign=RSAKeyUtils.doSignPrivateKey(text); System.out.println("签名:"+sign); System.out.println("验签结果:"+RSAKeyUtils.doVerifyPublicKey(text, sign)); } }