工作中用到的3DES加解密与RSA签名验签
3DES加密为对称加密算法,在Java实现中3DES的默认加密方式为ECB,默认填充方式为PKCS5Padding。密钥由服务方提供给客户方,即加解密都使用同一个密钥,所以只要有一方暴露了密钥就会存在安全问题。
RSA为非对称加密,需要有一对密钥,分别为公钥和私钥。如果使用者加解密过程,使用私钥加密,公钥解密;或者使用公钥加密,私钥解密。如果使用在签名和验签过程,则使用私钥签名,公钥验签;或者公钥签名,私钥验签。这样保证了只有一方暴露了密钥,不会产生安全威胁。
3DES加解密、DES加解密与RSA签名验签的Java实现:
public class EncryptUtil { private static final String CHAR_SET_UTF8 = "UTF-8"; private static final String ALGORITHM_3DES = "DESede"; private static final String ALGORITHM_3DES_PADDING = "DESede/ECB/PKCS5Padding"; private static final String ALGORITHM_DES = "DES"; private static final String ALGORITHM_MD5_WITH_RSA = "MD5withRSA"; private static final String ALGORITHM_RSA = "RSA"; /** * 3DES加密 * * @param content 加密内容 * @param key 密钥 * @return */ public static String tripleDESEncrypt(String content, byte[] key) { try { // 根据key转换为对应的SecretKey对象 DESedeKeySpec spec = new DESedeKeySpec(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_3DES); SecretKey tripleDesKey = keyFactory.generateSecret(spec); // 初始化为加密模式的密码器 Cipher cipher = Cipher.getInstance(ALGORITHM_3DES_PADDING); cipher.init(Cipher.ENCRYPT_MODE, tripleDesKey); // 加密 byte[] result = cipher.doFinal(content.getBytes(CHAR_SET_UTF8)); // 通过Base64转码返回 return Base64.encodeBase64String(result); } catch (Exception e) { log.error("3DES加密失败!", e); throw new BusinessException("3DES加密失败!", e); } } /** * 3DES解密 * * @param content 解密内容 * @param key 密钥 * @return */ public static String tripleDESDecrypt(byte[] content, byte[] key) { try { // 根据key转换为对应的SecretKey对象 DESedeKeySpec spec = new DESedeKeySpec(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_3DES); SecretKey tripleDesKey = keyFactory.generateSecret(spec); // 实例化 使用密钥初始化,设置为解密模式 Cipher cipher = Cipher.getInstance(ALGORITHM_3DES_PADDING); // 执行操作 cipher.init(Cipher.DECRYPT_MODE, tripleDesKey); byte[] result = cipher.doFinal(content); return new String(result); } catch (Exception e) { log.error("3DES解密失败额!", e); throw new BusinessException("3DES解密失败!", e); } } /** * DES加密 * * @param byteContent 加密内容 * @param key 密钥 * @return */ public static byte[] desEncrypt(byte[] byteContent, byte[] key) { try { // 根据key转换为对应的SecretKey对象 DESKeySpec desKeySpec = new DESKeySpec(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_DES); SecretKey desKey = keyFactory.generateSecret(desKeySpec); // 初始化为加密模式的密码器 Cipher cipher = Cipher.getInstance(ALGORITHM_DES); cipher.init(Cipher.ENCRYPT_MODE, desKey); // 加密 byte[] result = cipher.doFinal(byteContent); return result; } catch (Exception e) { log.error("3DES加密失败!", e); throw new BusinessException("3DES加密失败!", e); } } /** * DES解密 * * @param byteContent 加密内容 * @param key 密钥 * @return */ public static byte[] desDecrypt(byte[] byteContent, byte[] key) { try { // 根据key转换为对应的SecretKey对象 DESKeySpec desKeySpec = new DESKeySpec(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_DES); SecretKey desKey = keyFactory.generateSecret(desKeySpec); // 初始化为加密模式的密码器 Cipher cipher = Cipher.getInstance(ALGORITHM_DES); cipher.init(Cipher.DECRYPT_MODE, desKey); // 解密 byte[] result = cipher.doFinal(byteContent); return result; } catch (Exception e) { log.error("des解密失败!", e); throw new BusinessException("des解密失败!", e); } } /** * 生成MD5WithRSA数字签名 * * @param content 需要发送的报文内容 * @param privateKey 私钥 * @return * @throws Exception */ public static String generateMD5WithRSASign(String content, String privateKey) { try { // 生成私钥对象 KeyFactory factory = KeyFactory.getInstance(ALGORITHM_RSA); byte[] keyBytes2 = Base64.decodeBase64(privateKey); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes2); PrivateKey key = factory.generatePrivate(pkcs8EncodedKeySpec); byte[] contentBytes = content.getBytes(CHAR_SET_UTF8); // 返回MD5withRSA签名算法的 Signature对象 Signature signature = Signature.getInstance(ALGORITHM_MD5_WITH_RSA); signature.initSign(key); signature.update(contentBytes); byte[] signs = signature.sign(); return Base64.encodeBase64String(signs); } catch (Exception e) { log.error("生成数字签名异常!", e); throw new BusinessException("生成数字签名异常!", e); } } /** * 验证MD5WithRSA数字签名 * * @param content 接收到的报文内容 * @param sign 接收到的数字签名 * @param publicKey 公钥 * @return * @throws Exception */ public static boolean verifyMD5WithRSASign(String content, byte[] sign, String publicKey) { try { // 生成公钥对象 byte[] keyBytes = Base64.decodeBase64(publicKey); KeyFactory factory = KeyFactory.getInstance(ALGORITHM_RSA); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); PublicKey pubKey = factory.generatePublic(spec); // 对用md5和RSA私钥生成的数字签名进行验证 byte[] contentBytes = content.getBytes(CHAR_SET_UTF8); Signature signature = Signature.getInstance(ALGORITHM_MD5_WITH_RSA); signature.initVerify(pubKey); signature.update(contentBytes); return signature.verify(sign); } catch (Exception e) { log.error("验证数字签名异常!", e); throw new BusinessException("验证数字签名异常!", e); } } /** * 生成文件MD5摘要 * * @param file 文件 * @return */ public String generateFileMD5(File file) { FileInputStream inputStream = null; String md5Message = null; try { inputStream = new FileInputStream(file); md5Message = DigestUtils.md5Hex(inputStream); return md5Message; } catch (Exception e) { log.error("文件MD5异常!", e); throw new BusinessException("文件MD5异常!", e); } } /** * 生成密钥对,生成过后如果没有特殊情况不需要重新申请 * * @return * @throws Exception */ public static Map<String,String> generateKeyPair() { KeyPairGenerator keyGen = null; Map<String,String> keyMap = new HashMap<>(); try { keyGen = KeyPairGenerator.getInstance(ALGORITHM_RSA); // 秘钥长度 keyGen.initialize(1024); KeyPair keyPair = keyGen.generateKeyPair(); PrivateKey aPrivate = keyPair.getPrivate(); String privateKey = Base64.encodeBase64String(aPrivate.getEncoded()); PublicKey aPublic = keyPair.getPublic(); String publicKey = Base64.encodeBase64String(aPublic.getEncoded()); keyMap.put("privateKey",privateKey); keyMap.put("publicKey",publicKey); return keyMap; } catch (NoSuchAlgorithmException e) { throw new BusinessException("生成密钥对异常!", e); } } }
探索不以困难而止,学习不以艰苦而终