最近公司一直提及网络安全,特别是密码传输安全,由于LZ一直给运营商做web平台,切均为内网访问,所以也一直未使用https管理用户登陆和密码重置页面。首先声明若想做到彻底的密码安全,https是必需的,可以防止传输过程中的抓包窃取行为,从根本上解决密码泄露问题。LZ本次尝试的js端加密,java端解密的方式,只能从一定意义上实现密码安全传输,不能防止恶意模仿http进行请求操作。
LZ本次使用的是RSA非对称加密算法,该算法需要生成一个秘钥对,称为公钥和私钥,发送方使用公钥加密,接收方使用私钥解密,只要私钥不泄露,采用1024位方式生成的秘钥加密,几乎是不可能破解的,更多该加密算法详情,请自行了解。js端加解密,参考附件jsencrypt.zip,不做赘述,使用比较简单。RSA秘钥对的生成,使用OpenSSL工具1024位方式生成,网上亦有资料可供参考。
仅贴出java端代码供大家参考使用,其中public_key.txt和private_key.txt分别存放OpenSSL生成的公私钥信息,方便管理,同时此类需要引用第三方jar包bcprov-jdk14-138.jar,版本需自己选定。
package com.ai.wyw.utils; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.misc.BASE64Decoder; public final class RSAUtils { /** * openSSL生成的公钥串 */ private static final String DEFAULT_PUBLIC_KEY = ""; /** * openSSl生成的公钥串 */ private static final String DEFAULT_PRIVATE_KEY = ""; /** * 私钥 */ private static RSAPrivateKey privateKey; /** * 公钥 */ private static RSAPublicKey publicKey; /** * 字节数据转字符串专用集合 */ private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * 私有构造方法 */ private RSAUtils() { } /** * 获取私钥 * * @return 当前的私钥对象 */ public static RSAPrivateKey getPrivateKey() { return privateKey; } /** * 获取公钥 * * @return 当前的公钥对象 */ public static RSAPublicKey getPublicKey() { return publicKey; } /** * 随机生成密钥对 */ public static void genKeyPair() { KeyPairGenerator keyPairGen = null; try { keyPairGen = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyPairGen.initialize(1024, new SecureRandom()); KeyPair keyPair = keyPairGen.generateKeyPair(); privateKey = (RSAPrivateKey) keyPair.getPrivate(); publicKey = (RSAPublicKey) keyPair.getPublic(); } /** * 从文件中输入流中加载公钥 * * @param in * 公钥输入流 * @throws Exception * 加载公钥时产生的异常 */ public static void loadPublicKey(InputStream in) throws Exception { try { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } loadPublicKey(sb.toString()); } catch (IOException e) { throw new Exception("公钥数据流读取错误"); } catch (Exception e) { throw new Exception("公钥输入流为空"); } } /** * 从字符串中加载公钥 * * @param publicKeyStr * 公钥数据字符串 * @throws Exception * 加载公钥时产生的异常 */ public static void loadPublicKey(String publicKeyStr) throws Exception { try { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("公钥非法"); } catch (IOException e) { throw new Exception("公钥数据内容读取错误"); } catch (Exception e) { throw new Exception("公钥数据为空"); } } /** * 从文件中加载私钥 * * @param keyFileName * 私钥文件名 * @return 是否成功 * @throws Exception */ public static void loadPrivateKey(InputStream in) throws Exception { try { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } loadPrivateKey(sb.toString()); } catch (IOException e) { throw new Exception("私钥数据读取错误"); } catch (NullPointerException e) { throw new Exception("私钥输入流为空"); } } public static void loadPrivateKey(String privateKeyStr) throws Exception { try { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("私钥非法"); } catch (IOException e) { throw new Exception("私钥数据内容读取错误"); } catch (Exception e) { throw new Exception("私钥数据为空"); } } /** * 加密过程 * * @param publicKey * 公钥 * @param plainTextData * 明文数据 * @return * @throws Exception * 加密过程中的异常信息 */ public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception { if (publicKey == null) { throw new Exception("加密公钥为空, 请设置"); } Cipher cipher = null; try { cipher = Cipher.getInstance("RSA", new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] output = cipher.doFinal(plainTextData); return output; } catch (NoSuchAlgorithmException e) { throw new Exception("无此加密算法"); } catch (NoSuchPaddingException e) { e.printStackTrace(); return null; } catch (InvalidKeyException e) { throw new Exception("加密公钥非法,请检查"); } catch (IllegalBlockSizeException e) { throw new Exception("明文长度非法"); } catch (Exception e) { throw new Exception("明文数据已损坏"); } } /** * 解密过程 * * @param privateKey * 私钥 * @param cipherData * 密文数据 * @return 明文 * @throws Exception * 解密过程中的异常信息 */ public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception { if (privateKey == null) { throw new Exception("解密私钥为空, 请设置"); } Cipher cipher = null; try { cipher = Cipher.getInstance("RSA", new BouncyCastleProvider()); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] output = cipher.doFinal(cipherData); return output; } catch (NoSuchAlgorithmException e) { throw new Exception("无此解密算法"); } catch (NoSuchPaddingException e) { e.printStackTrace(); return null; } catch (InvalidKeyException e) { throw new Exception("解密私钥非法,请检查"); } catch (IllegalBlockSizeException e) { throw new Exception("密文长度非法"); } catch (Exception e) { throw new Exception("密文数据已损坏"); } } /** * 字节数据转十六进制字符串 * * @param data * 输入数据 * @return 十六进制内容 */ public static String byteArrayToString(byte[] data) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < data.length; i++) { // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移 stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]); // 取出字节的低四位 作为索引得到相应的十六进制标识符 stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]); if (i < data.length - 1) { stringBuilder.append(' '); } } return stringBuilder.toString(); } public static void main(String[] args) { // rsaEncrypt.genKeyPair(); // 加载秘钥 try { //rsaUtils.loadPublicKey(RSAUtils.DEFAULT_PUBLIC_KEY); //rsaUtils.loadPrivateKey(RSAUtils.DEFAULT_PUBLIC_KEY); RSAUtils.loadPublicKey(new FileInputStream(new File("public_key.txt"))); RSAUtils.loadPrivateKey(new FileInputStream(new File("private_key.txt"))); } catch (Exception e) { System.out.println(e.getMessage()); } // 测试字符串 String encryptStr = 1234!@#$; try { // 加密 byte[] cipher = RSAUtils.encrypt(RSAUtils.getPublicKey(), encryptStr.getBytes()); // 解密 byte[] plainText = RSAUtils.decrypt(RSAUtils.getPrivateKey(), cipher); System.out.println("密文长度:" + cipher.length); System.out.println(RSAUtils.byteArrayToString(cipher)); System.out.println("明文长度:" + plainText.length); System.out.println(RSAUtils.byteArrayToString(plainText)); System.out.println(new String(plainText)); } catch (Exception e) { System.out.println(e.getMessage()); } } }
LZ看过一些关于密码安全的书籍,采用md5withRSA的数字签名的方式,可以很好的解决此类问题,首先使用md5方式生成内容摘要,对内容+salt进行公钥加密,一起发送后台,对密文内容私钥解密后去salt生成md5摘要,对比前台发送的md5摘要值,确保内容是否伪造,对此LZ没有进行实现,但的确是一个完善的安全策略。
相关推荐
客户端的`jsencrypt.js`库是一个JavaScript实现的RSA加密工具,它允许在浏览器端进行加密操作。`common.js`可能包含辅助函数或配置,以帮助JavaScript代码执行加密过程。`JS加密,java服务端解密,采用RAS非对称加密...
经过本人修改,简化并完善了别人的代码,使其更加的容易理解和学习! 此为一个完整的项目,...功能:服务端随机生成密钥,JS用公钥加密,服务端用私钥解密。用到的JS加密文件是从官网下载的最新版,速度快,稳定性好!
JavaScript客户端RSA加密与Java服务端解密是一种常见的安全通信机制,尤其在Web应用中,用于保护敏感数据,如用户密码、API密钥等。这里我们将深入探讨这一过程,包括RSA算法的基本原理,JavaScript中的实现,以及...
通过分析和理解这些代码,我们可以更好地掌握AES+RSA加密服务端的工作原理和实现细节。 综上所述,"AES+RSA加解密服务端"是信息安全领域的一个重要应用,它利用了两种加密算法的优势,确保了数据在传输过程中的安全...
如果源码与此有关,可能涉及将RSA加密应用于Word文档内容的某部分,或者是在处理XML数据时使用了RSA加密。 8. **安全注意事项**: 在实际应用中,务必妥善保管私钥,避免暴露。同时,由于RSA的加密速度较慢,通常...
Java提供了强大的Java Cryptography Architecture (JCA) 和Java Cryptography Extension (JCE),它们包含了处理RSA加密解密的类和接口,如`java.security.KeyPairGenerator`用于生成密钥对,`javax.crypto.Cipher`...
通过分析和理解这段源码,开发者可以更好地掌握.NET下RSA加密解密的实际应用,为自己的项目提供安全保障。 总的来说,基于.NET的RSA私钥加密和公钥解密是.NET开发中一个重要的安全功能,它结合了理论与实践,为网络...
在iOS平台上使用Objective-C进行RSA加密和解密通常涉及几个步骤,包括生成RSA密钥对、使用公钥加密数据、以及使用私钥解密数据。以下是一个简化的步骤说明和示例代码,展示了如何使用Objective-C和CommonCrypto库...
在提供的压缩包中,有两个Java文件(RSACrypt.java和RSACryptTest.java)和一个JavaScript文件(jsencrypt.min.js),这表明代码实现了RSA加密解密的Java版本和JavaScript版本,可以在客户端和服务端之间进行安全的...
在Flutter和Java混合开发的场景中,"flutter加密java解密"的主题涉及到如何在Flutter客户端与Java后台之间进行安全的数据交互,确保信息在传输过程中不被窃取或篡改。这里我们将详细讨论如何实现这一目标,并保证App...
1.首页需要公钥私钥 生成方法百度很多; 在flutter中,密钥文件直接存放在目录中是无法使用File读取到的,只能放在asset中才可以,所以需要在 pubspec.yaml中增加相关密钥文件才...3.创建加密辅助类EncryptHelper.dart
在JavaEE环境中,RSA加密通常用于以下几个关键场景: 1. **HTTPS通信**:在服务器与客户端之间建立安全的HTTPS连接时,RSA可以用于交换会话密钥。服务器会提供其公钥,客户端使用该公钥加密会话密钥并发送给服务器...
这篇博文"关于使用JS前台加密、JAVA后台解密的RSA实现,RSA加密和签名"探讨了如何在JavaScript前端进行RSA加密,并在Java后端进行解密,以及如何使用RSA进行数字签名。 RSA加密的核心在于一对公钥和私钥。公钥用于...
《易语言Linux加密服务端详解》 在信息技术领域,安全始终是至关重要的议题。本文将深入探讨基于易语言编写的Linux加密服务端源码,它为开发者提供了一种在Linux系统上实现控制台加密服务的方法。易语言,作为国内...
本文将深入探讨iOS平台上的RSA加密与解密技术,包括基本原理、实现方式以及相关的注意事项。 RSA(Rivest–Shamir–Adleman)算法是一种公开密钥加密技术,由Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出...
`RSA`是一种非对称加密算法,它使用一对公钥和私钥进行数据加密和解密,以确保在网络传输过程中数据的安全性。 首先,让我们深入了解一下`SOCKET`通信。在`C#`中,`System.Net.Sockets`命名空间提供了一套完整的`...
4. **非对称加密算法**:如RSA,使用一对公钥和私钥,公钥用于加密,私钥用于解密。这种方法安全性更高,但计算量较大,不适用于大块数据的加密。 5. **许可证验证**:在解密过程中,许多脚本加密器会添加许可证...