使用RSA非对称加密登陆界面登陆密码,防止明文传输
2016-12-27 12:39
531 查看
一、RSA的概念
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用,在java中可用作表单密码加密,工作原理可理大致是,首先服务器端会产生一对公钥和私钥,然后客户端在需要加密的时候会异步请求服务器端,获取公钥,并利用公钥进行加密操作(加密表单密码元素),服务器端收到加了密的用户密码,再使用私钥进行解密,从而获取加密前的明文密码。由于仅仅有了公钥并不能解密,必须使用服务器的私钥解码,所以在web端的项目中使用时能提高密码的安全性。二、实现过程(代码)
1.需要jar包以及js插件:bcprov-ext-jdk15on-1.55.jar,jquery.jcryption-1.1.js(附件有)2. 登陆页面,分2种:
第一种直接是表单form提交:处理思路是提交ajax请求异步获得公钥,使用jquery获取页面所有type='password'的input框,然后循环遍历,并同时将加密的密码值放到对应的type='password'的input框中,然后点击提交按钮即可发送请求
第二种是点击按钮后使用ajax请求提交:
js代码:
/** * 单击登陆按钮 */ $("#logInpt").click(function(){ //访问后台获取公钥 $.jCryption.getKeys(url,function(receivedKeys){ // 异步请求获取用来加密的公钥 keys = receivedKeys; if( null != keys && "undefined" != keys){ var postData = {}; var origPwd = $("#J_PasswordPsd").val(); //实用公钥进行加密 $.jCryption.encrypt(origPwd, keys, function(encryptedPasswd) { ///使用公钥谨慎性加密 var serlizeFormData =$("#J_ValidForm").serializeArray();//获取表单的序列化元素 $.each(serlizeFormData,function(key,val){ //将提交的参数中的密码进行处理 if(val['name']=="password" && val['value']==origPwd){ postData["password"] = encryptedPasswd; }else{ postData[val.name]=val['value']; } }) //修改参数后提交ajax请求 $.ajax({ url:'', beforeSend:,//提交前事件处理方法 type:"post", dataType:"json", data:postData, success:function(){ }//回掉函数处理 }) // usrForm.submit(); }) } }); })java代码(Config存储静态代码块,执行RSAutil中的代码,产生密钥
,也可以采用将生成的密钥保存到seesion中,然后揭秘时候从session中取的方法):
@RequestMapping(value = "/getPublicKey.htm", method = { RequestMethod.GET }) public void encryptionWithPublicKey(HttpServletRequest request,HttpServletResponse response){ String generateKeypair = request.getParameter("generateKeypair"); try{ if (generateKeypair != null && ("true").equals(generateKeypair)) { Map<String ,Object> keyMap = Config.getRsaKeyMap(); //RSAUtil RSAUtil = new RSAUtil(); if (keyMap == null) { String basePath = "config/ds.properties"; KeyPair kp = RSAUtil.generateKeypair(1024, basePath); Map<String, Object> map = new HashMap<String,Object>(); map.put("keyPair",kp); keyMap = map; } KeyPair keyPair = (KeyPair)keyMap.get("keyPair"); StringBuffer output = new StringBuffer(); String e = RSAUtil.getPublicKeyExponent(keyPair); String n = RSAUtil.getPublicKeyModulus(keyPair); String md = String.valueOf(RSAUtil.getMaxDigits(1024)); output.append("{\"e\":\""); output.append(e); output.append("\",\"n\":\""); output.append(n); output.append("\",\"maxdigits\":\""); output.append(md); output.append("\"}"); output.toString(); response.getOutputStream().print(output.toString().replaceAll("\r", "").replaceAll("\n", "").trim()); } }catch(Exception e){ e.printStackTrace(); } }产生密钥对的工具类:
public class RSAUtil { public static final String PUBLIC_KEY = "RSAPublicKey"; public static final String PRIVATE_KEY = "RSAPrivateKey"; public static final String BASEPATH = "config/ds.properties"; public static final java.security.Provider provider = new BouncyCastleProvider(); /** * Constructor */ public RSAUtil() throws Exception { java.security.Security.addProvider(provider); } /** * Generates the Keypair with the given keyLength. * * @param keyLength * length of key * @return KeyPair object * @throws RuntimeException * if the RSA algorithm not supported */ public static KeyPair generateKeypair(int keyLength,String basePath) throws Exception { try { KeyPairGenerator kpg; try { kpg = KeyPairGenerator.getInstance("RSA"); } catch (Exception e) { kpg = KeyPairGenerator.getInstance("RSA",provider); } kpg.initialize(keyLength); KeyPair keyPair = kpg.generateKeyPair(); // saveKeyPair(keyPair, basePath); return keyPair; } catch (NoSuchAlgorithmException e1) { throw new RuntimeException("RSA algorithm not supported", e1); } catch (Exception e) { throw new Exception("other exceptions", e); } } /** * 保存密钥 * @param kp * @throws Exception */ public static void saveKeyPair(KeyPair kp, String basePath) throws Exception { basePath =StringUtils.isNotBlank(basePath)?basePath:BASEPATH; String path = Thread.currentThread().getContextClassLoader().getResource(basePath).getPath(); Properties prop = new Properties();// 属性集合对象 InputStream fis = new BufferedInputStream(new FileInputStream(path));// 属性文件输入流 prop.load(fis);// 将属性文件流装载到Properties对象中 fis.close();// 关闭流 // 修改公钥值的属性值 prop.setProperty(PUBLIC_KEY,byteArrayToHexString(kp.getPublic().getEncoded())); // 修改私钥值的属性值 prop.setProperty(PRIVATE_KEY,byteArrayToHexString(kp.getPrivate().getEncoded())); // 文件输出流 BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(path)); // 将Properties集合保存到流中 prop.store(fos, "modify"); fos.flush(); fos.close();// 关闭流 //System.out.println("获取修改后的属性值:password=" + prop.getProperty("password")); } /** * Decrypts a given string with the RSA keys * * @param encrypted * full encrypted text * @param keys * RSA keys * @return decrypted text * @throws RuntimeException * if the RSA algorithm not supported or decrypt operation failed */ public static String decrypt(String encrypted, KeyPair keys) throws Exception { Cipher dec; try { try { dec = Cipher.getInstance("RSA/NONE/NoPadding"); } catch (Exception e) { dec = Cipher.getInstance("RSA/NONE/NoPadding",provider); } dec.init(Cipher.DECRYPT_MODE, keys.getPrivate()); } catch (GeneralSecurityException e) { throw new RuntimeException("RSA algorithm not supported", e); } String[] blocks = encrypted.split("\\s"); StringBuffer result = new StringBuffer(); try { for (int i = blocks.length - 1; i >= 0; i--) { byte[] data = hexStringToByteArray(blocks[i]); byte[] decryptedBlock = dec.doFinal(data); result.append(new String(decryptedBlock)); } } catch (GeneralSecurityException e) { throw new RuntimeException("Decrypt error", e); } /** * Some code is getting added in first 2 digits with Jcryption need to investigate */ return result.reverse().toString().substring(2); } /** * Parse url string (Todo - better parsing algorithm) * * @param url * value to parse * @param encoding * encoding value * @return Map with param name, value pairs */ public static Map parse(String url, String encoding) { try { String urlToParse = URLDecoder.decode(url, encoding); String[] params = urlToParse.split("&"); Map parsed = new HashMap(); for (int i = 0; i < params.length; i++) { String[] p = params[i].split("="); String name = p[0]; String value = (p.length == 2) ? p[1] : null; parsed.put(name, value); } return parsed; } catch (UnsupportedEncodingException e) { throw new RuntimeException("Unknown encoding.", e); } } /** * Return public RSA key modulus * * @param keyPair * RSA keys * @return modulus value as hex string */ public static String getPublicKeyModulus(KeyPair keyPair) { RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); return publicKey.getModulus().toString(16); } /** * Return public RSA key exponent * * @param keyPair * RSA keys * @return public exponent value as hex string */ public static String getPublicKeyExponent(KeyPair keyPair) { RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); return publicKey.getPublicExponent().toString(16); } /** * Max block size with given key length * * @param keyLength * length of key * @return numeber of digits */ public static int getMaxDigits(int keyLength) { return ((keyLength * 2) / 16) + 3; } /** * Convert byte array to hex string * * @param bytes * input byte array * @return Hex string representation */ public static String byteArrayToHexString(byte[] bytes) { StringBuffer result = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { result.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16) .substring(1)); } return result.toString(); } /** * Convert hex string to byte array * * @param data * input string data * @return bytes */ public static byte[] hexStringToByteArray(String data) { int k = 0; byte[] results = new byte[data.length() / 2]; for (int i = 0; i < data.length();) { results[k] = (byte) (Character.digit(data.charAt(i++), 16) << 4); results[k] += (byte) (Character.digit(data.charAt(i++), 16)); k++; } return results; } /** * @param args */ public static void main(String[] args) { /* KeyPair keyPair = generateKeypair(1024, ""); String pwd = "11111111"; System.out.println(jCryption.toPublicKeyString()); */ } }RSA解密的部分代码(config中使用静态变量存储密钥对)
//RSA解密 Map<String ,Object> keyMap = Config.getRsaKeyMap(); KeyPair keys = (KeyPair)keyMap.get("keyPair"); String decryptedPass = RSAUtil.decrypt(password, keys); //RSA解密至此,有关RSA加密解密就结束了,下面附上文章开始提到的文件,jar可以从maen中央仓库下载,js提供一下
相关文章推荐
- 用RSA加密实现Silverlight登录密码加密传输
- 用RSA加密实现Web登录密码加密传输
- SQLSERVER使用密码加密备份文件以防止未经授权还原数据库
- 使用C#+ASP.NET来进行RSA(非对称)加密.
- SQLSERVER使用密码加密备份文件以防止未经授权还原数据库
- 用RSA加密实现Web登录密码加密传输
- SQLSERVER使用密码加密备份文件以防止未经授权还原数据库
- openssl 非对称加密DSA,RSA区别与使用介绍(转)
- 用RSA加密实现Web登录密码加密传输
- 用RSA加密实现Web登录密码加密传输
- 用RSA加密实现Web登录密码加密传输
- 用RSA实现Web单点登录密码的加密传输
- 使用RSA实现客户端和后台的非对称加密
- 用RSA加密实现Web登录密码加密传输
- sftp,putty使用非对称密钥RSA无需密码登录远程主机
- android SharedPreference的简单使用(登陆界面记住密码)
- 登陆验证前对用户名和密码加密之后传输数据---base64加密
- TCP传输中使用AES加密和gizp压缩(2)--封装TcpUtil,封装后实现登陆
- 使用非对称RSA加密
- 发个牢骚,博客园登录依旧使用HTTP明文传输密码,有木有!