今天研究了一下关于登录密码加密的问题,下面来说说实现。

一、RSA非对称加密:

具体流程如下:截取自http://blog.csdn.net/m372897500/article/details/50905017

  • 客户端向服务器第一次发起登录请求(不传输用户名和密码)。
  • 服务器利用RSA算法产生一对公钥和私钥。并保留私钥, 将公钥发送给客户端。
  • 客户端收到公钥后, 加密用户密码, 向服务器发起第二次登录请求(传输用户名和加密后的密码)。
  • 服务器利用保留的私钥对密文进行解密,得到真正的密码。
其实这个加密还是比较简单的,不过也要注意其中的几个问题,在我使用的过程中就出现了:
1.最好要base64对生成公钥私钥进行再编码,当使用时自然也要再次使用base64解码
2.RSA对加密字符串有限定,1024最多只能加密117个字符串,需要进行一些分块,否则很容易解密失败,记录一下解决方法,生成key的方法这里就省略了,网上一堆,可以参考该文章:http://blog.csdn.net/centralperk/article/details/8558678
/*** 公钥加密** @param data* @param publicKey* @return* @throws Exception*/public static String encryptByPublicKey(String data, RSAPublicKey publicKey)throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 模长int key_len = publicKey.getModulus().bitLength() / 8;// 加密数据长度 <= 模长-11String[] datas = splitString(data, key_len - 11);String mi = "";//如果明文长度大于模长-11则要分组加密for (String s : datas) {mi += bcd2Str(cipher.doFinal(s.getBytes()));}return mi;}/*** 私钥解密** @param data* @param privateKey* @return* @throws Exception*/public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);//模长int key_len = privateKey.getModulus().bitLength() / 8;byte[] bytes = data.getBytes();byte[] bcd = ASCII_To_BCD(bytes, bytes.length);System.err.println(bcd.length);//如果密文长度大于模长则要分组解密String ming = "";byte[][] arrays = splitArray(bcd, key_len);for(byte[] arr : arrays){ming += new String(cipher.doFinal(arr));}return ming;}public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {byte[] bcd = new byte[asc_len / 2];int j = 0;for (int i = 0; i < (asc_len + 1) / 2; i++) {bcd[i] = asc_to_bcd(ascii[j++]);bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));}return bcd;}public static byte asc_to_bcd(byte asc) {byte bcd;if ((asc >= '0') && (asc <= '9'))bcd = (byte) (asc - '0');else if ((asc >= 'A') && (asc <= 'F'))bcd = (byte) (asc - 'A' + 10);else if ((asc >= 'a') && (asc <= 'f'))bcd = (byte) (asc - 'a' + 10);elsebcd = (byte) (asc - 48);return bcd;}/*** BCD转字符串*/public static String bcd2Str(byte[] bytes) {char temp[] = new char[bytes.length * 2], val;for (int i = 0; i < bytes.length; i++) {val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');val = (char) (bytes[i] & 0x0f);temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');}return new String(temp);}/*** 拆分字符串*/public static String[] splitString(String string, int len) {int x = string.length() / len;int y = string.length() % len;int z = 0;if (y != 0) {z = 1;}String[] strings = new String[x + z];String str = "";for (int i=0; i<x+z; i++) {if (i==x+z-1 && y!=0) {str = string.substring(i*len, i*len+y);}else{str = string.substring(i*len, i*len+len);}strings[i] = str;}return strings;}/***拆分数组*/public static byte[][] splitArray(byte[] data,int len){int x = data.length / len;int y = data.length % len;int z = 0;if(y!=0){z = 1;}byte[][] arrays = new byte[x+z][];byte[] arr;for(int i=0; i<x+z; i++){arr = new byte[len];if(i==x+z-1 && y!=0){System.arraycopy(data, i*len, arr, 0, y);}else{System.arraycopy(data, i*len, arr, 0, len);}arrays[i] = arr;}return arrays;}
还有就是关于密文的问题,如果你想要每次生成不一样的密文,生成秘钥的时候使用:
RSA/None/PKCS1Padding

想要一样的密文,生成秘钥的时候使用:

RSA/NONE/NoPadding

参考文章:http://blog.csdn.net/defonds/article/details/42775183

二、MD5加盐加密:没看错,是加盐,有兴趣去度娘看看介绍,现在说说实现,例如密码为123456,此处我们规定盐值为其hashcode,即要加密的字符串为

 password + password.hashCode()

方法如下:

    /*** 获取十六进制字符串形式的MD5*/public static String toMD5Code(byte[] bytes) {StringBuffer sb = new StringBuffer();try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.reset();md5.update(bytes);byte[] after = md5.digest();for (int i = 0; i < after.length; i++) {
//                int num = after[i] & 0xff;String hex = Integer.toHexString(0xff & after[i]);if (hex.length() == 1)hex = "0" + hex;sb.append(hex);}} catch (Exception ex) {ex.printStackTrace();}return sb.toString();}

使用的时候注意,需要规范为UTF-8

String password = "123456";
String tempPwd = password + password.hashCode();try {passwordMD5 = toMD5Code(tempPwd.getBytes("UTF-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}

还是很简单的,只要加密的密文和服务器加密得到结果一致,验证就会通过,注意两边一定要统一规则即可。注意MD5加密是不可逆的。

三、Base64加密:截取自http://www.tuicool.com/articles/EBBBni
// 加密传入的数据是byte类型的,并非使用decode方法将原始数据转二进制,String类型的数据 使用 str.getBytes()即可
String str = "Hello!";
// 在这里使用的是encode方式,返回的是byte类型加密数据,可使用new String转为String类型
String strBase64 = new String(Base64.encode(str.getBytes(), Base64.DEFAULT));
Log.i("Test", "encode >>>" + strBase64);// 这里 encodeToString 则直接将返回String类型的加密数据
String enToStr = Base64.encodeToString(str.getBytes(), Base64.DEFAULT);
Log.i("Test", "encodeToString >>> " + enToStr);// 对base64加密后的数据进行解密
Log.i("Test", "decode >>>" + new String(Base64.decode(strBase64.getBytes(), Base64.DEFAULT)));


注意下base64的问题,如下链接

http://www.360doc.com/content/11/0602/14/1542811_121186311.shtml
4.AES256加密:这里使用的是传入16位的字符串作为秘钥。
public class AES256EncryptionUtil {public static final String TAG = AES256EncryptionUtil.class.getSimpleName();public static final String ALGORITHM = "AES/ECB/PKCS7Padding";private static String mPassword = "";  //秘钥字符串/*** 一次性设置password,后面无需再次设置* @param password*/public static void setPassword(String password){mPassword = password;}/*** 生成key* @param password* @return* @throws Exception*/private static byte[] getKeyByte(String password) throws Exception {byte[] seed = new byte[24];if(!TextUtils.isEmpty(password)) {seed = password.getBytes();}return seed;}/*** 加密* @param data* @return*/public static String encrypt(String data) throws Exception{String string = "";byte[] keyByte = getKeyByte(mPassword);SecretKeySpec keySpec = new SecretKeySpec(keyByte,"AES"); //生成加密解密需要的Keybyte[] byteContent = data.getBytes("utf-8");Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");cipher.init(Cipher.ENCRYPT_MODE, keySpec);byte[] result = cipher.doFinal(byteContent);string = parseByte2HexStr(result);  //转成Stringreturn string;}/*** 解密* @param data* @return*/public static String decrypt(String data) throws Exception{String string = "";byte[] keyByte = getKeyByte(mPassword);byte[] byteContent = parseHexStr2Byte(data);  //转成byteCipher cipher = Cipher.getInstance(ALGORITHM, "BC");SecretKeySpec keySpec = new SecretKeySpec(keyByte,"AES"); //生成加密解密需要的Keycipher.init(Cipher.DECRYPT_MODE, keySpec);byte[] decoded = cipher.doFinal(byteContent);string = new String(decoded);return string;}/*** 转化为String* @param buf* @return*/private static String parseByte2HexStr(byte buf[]) {StringBuffer sb = new StringBuffer();for (int i = 0; i < buf.length; i++) {String hex = Integer.toHexString(buf[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sb.append(hex.toUpperCase());}return sb.toString();}/*** 将16进制转换为二进制* @param hexStr* @return*/private static byte[] parseHexStr2Byte(String hexStr) {if (hexStr.length() < 1)return null;byte[] result = new byte[hexStr.length() / 2];for (int i = 0; i < hexStr.length() / 2; i++) {int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);result[i] = (byte) (high * 16 + low);}return result;}
AES上面的加密是根据定义的password生成的,要说为了安全起见,可以使用随机源来生成,可以改成这样:
/*** 加密 - 随机源* @param content* @return*/public static byte[] encrypt(String content) {try {//"AES":请求的密钥算法的标准名称KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");sr.setSeed(tohash256Deal(mPassword));//256:密钥生成参数;securerandom:密钥生成器的随机源SecureRandom securerandom = new SecureRandom(tohash256Deal(mPassword));kgen.init(256, sr);//生成秘密(对称)密钥SecretKey secretKey = kgen.generateKey();//返回基本编码格式的密钥byte[] enCodeFormat = secretKey.getEncoded();//根据给定的字节数组构造一个密钥。enCodeFormat:密钥内容;"AES":与给定的密钥内容相关联的密钥算法的名称SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");//创建一个实现指定转换的 Cipher对象,该转换由指定的提供程序提供。//"AES/ECB/PKCS7Padding":转换的名称;"BC":提供程序的名称Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] byteContent = content.getBytes("utf-8");byte[] cryptograph = cipher.doFinal(byteContent);return Base64.encode(cryptograph,Base64.DEFAULT);} catch (Exception e) {e.printStackTrace();LogHelper.e("lenita","e en"+e.toString());}return null;}/*** 解密 - 随机源* @param cryptograph* @return*/public static String decrypt(byte[] cryptograph) {try {KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");sr.setSeed(tohash256Deal(mPassword));
//            SecureRandom securerandom = new SecureRandom(tohash256Deal(mPassword));kgen.init(256, sr);SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");cipher.init(Cipher.DECRYPT_MODE, key);byte[] content = cipher.doFinal(Base64.decode(cryptograph,Base64.DEFAULT));return new String(content);} catch (Exception e) {e.printStackTrace();LogHelper.e("lenita","e de ="+e.toString());}return null;}

上面是参考了很多资料得到的答案,最重要的就是随机源函数,如果直接new会抛出异常,所以我们要:
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(tohash256Deal(mPassword));

App安全登录之密码、通讯加密方法(MD5,Base64,RSA,AES)相关推荐

  1. php js记住密码功能,jquery.cookie.js实现用户登录保存密码功能的方法_jquery

    本文实例讲述了jquery.cookie.js实现用户登录保存密码功能的方法.分享给大家供大家参考,具体如下: 需要导入的js有jquery.js和jquery.cookie.js 在页面加载时首先尝 ...

  2. DM8登录用户名密码增强加密

    登录用户名密码增强加密 生成公钥和私钥 ./dmkey PATH=/tmp 生成的文件名为dm_login.prikey和dm_login.pubkey 显示私钥的相关信息 ./dmkey prike ...

  3. 用户登录对密码进行加密

    离开上家公司后才发现上家公司的网站 用户登录 对密码是没有任何加密的形式,自己整理了一下对密码加密的方法 如下: 不加密: 我们使用网络探测器能轻易的获取用户的用户名密码,如果这些信息被不发份子获得, ...

  4. Windows用户密码的加密方法与破解

    再研究Hastcat的时候涉及到了Windows的Hash破解,感觉这个地方还是有一些姿势点和细节的,特此写文章记录之. Hash简介 Hash 一般翻译为"散列",也可直接音译为 ...

  5. 登录注册的基本加密方法(可逆)

    加密算法 private static final byte[] DES_KEY = { 21, 1, -110, 82, -32, -85, -128, -65 };@SuppressWarning ...

  6. mysql 密码字段加密_phpmyadmin密码字段加密方法

    eclipse开发 javafx(转) 了解过JavaFX的都知道,JavaFX自从2.0版本开始,已经完全抛弃了之前的script语言,才用纯java来实现.这样的好处就是1.让使用Java的IDE ...

  7. MD5加密与用户名密码批量加密方法

    public static String generatePwd(String salt, String originalPassword) { byte[] hash = md5obj.digest ...

  8. python常见加密方法实现,DES,AES,RSA,MD5,国密。--更新中

    常见加密算法的简介和python的实现,使用各种库实现,而不是源码实现 对称加密 DES加密 非对称加密 RSA加密 消息摘要算法/签名算法 MD5 国密算法 SM1 对称密码 SM4 对称算法 SM ...

  9. 一种简便的ios图片加密方法-对图片进行base64编码

    最近项目中需要对图片的安全做处理,保证用户(即使是越狱用户)也不能查看到从服务器中下载下来的图片. 折腾了多种方法,发现还是使用base64对储存的文件进行一次编码最方便,编码之后,用户打开图片时将显 ...

最新文章

  1. 青龙羊毛——宝石星球(教程)
  2. win2008服务器维护费用,win2008 服务器安全检查步骤指引(日常维护说明)
  3. 高通平台如何新增加一个分区,并mount到android系统中
  4. 传统的 IT 销售渠道将会走向末路?
  5. Syncfusion的新JavaScript条形码生成器控件
  6. DSL(domain specific language )
  7. 优盘文件或目录损坏且无法读取怎样解决
  8. 阿里云国际版短信验证码及服务教程
  9. YOLOv5+TensorRT+Win11(Python版)
  10. MySQL 文件结构、逻辑架构及 sql 执行流程分析作者:Java后端架构
  11. 计算机网络的安全性在哪里,计算机网络面临的安全性威胁可分为哪两类分别包含..._安全工程师_帮考网...
  12. verilog实现时钟的时和分,其中时为24进制,分为60进制
  13. java float是_java中float是什么意思
  14. JavaScript - 用对象的方式创建数组
  15. token放在那里 url_token在项目生成和使用
  16. 理解Unity3D中的四种坐标体系
  17. rtsp 报文转发_RSTP技术详解
  18. 最好的视频会议软件gotomeeting
  19. ardupilot 核心IMU数据记录
  20. 大唐杯5G考前冲刺篇(回顾全文重点必看)

热门文章

  1. 2015中国创新型软件公司TOP100排行榜
  2. iOS 隐藏导航条左边返回按钮
  3. web开发过程中,浏览器无法弹出Excel下载的提示
  4. 安装ADOBE reader时出现找不到actionlist的解决办法
  5. FineReport填报报表
  6. finereport字段显示设置_FineReport基本用法
  7. 用 unity3D 探究飞机投弹问题
  8. 问题 BR: 笨鸟先飞
  9. python爬虫淘宝和天猫的区别_荐真实难过,当python爬虫对上淘宝和天猫,我又失败了!...
  10. 8251和8086串口通信输入和输出Proteus仿真