安卓简单密码
消息摘要算法(单向散列函数)
MD5
不管明文多长散列后密文定长
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.xiaojianbang.app;
import java.security.MessageDigest;
public class MD5 { public static String md5_1(String args) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5", "BC"); md.update(args.getBytes()); return Utils.byteToHexString(md.digest()); }
public static String md5_1(String args, boolean bool) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5", "BC"); md.update(args.getBytes(), 2, 5); return Utils.byteToHexString(md.digest("xiaojianbang".getBytes())); } }
|
MD5本质来说是16个字节,我们平时看到的一般是32位的原因是把这16个字节进行了HEX的编码,两个十六进制数代表一个字节
32个十六进制数
update是可以被调用多次的
SHA1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.xiaojianbang.app;
import java.security.MessageDigest;
public class SHA { public static String sha_1(String args) throws Exception { MessageDigest md = MessageDigest.getInstance("SHA-1", "BC"); md.update(args.getBytes()); return Utils.byteToHexString(md.digest()); }
public static String sha_2(String args) throws Exception { MessageDigest md = MessageDigest.getInstance("SHA-1", "BC"); md.update(args.getBytes(), 2, 5); return Utils.byteToHexString(md.digest("xiaojianbang".getBytes())); } }
|
相对于MD5来说没有什么区别
MAC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.xiaojianbang.app;
import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec;
public class MAC { public static String mac_1(String args) throws Exception { SecretKey key = new SecretKeySpec("87654321".getBytes(), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(key); mac.update(args.getBytes()); return Utils.byteToHexString(mac.doFinal()); }
public static String mac_2(String args) throws Exception { SecretKey key = new SecretKeySpec("87654321".getBytes(), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(key); mac.update(args.getBytes(), 2, 5); return Utils.byteToHexString(mac.doFinal("xiaojianbang".getBytes())); } }
|
SecretKeySpec一般用来实例化一个密钥
对称加密
DES
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.xiaojianbang.app;
import android.util.Base64; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec;
public class DES { public static String des_1(String args) throws Exception { SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec("12345678".getBytes())); AlgorithmParameterSpec iv = new IvParameterSpec("87654321".getBytes()); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(1, secretKey, iv); cipher.update(args.getBytes()); return Base64.encodeToString(cipher.doFinal(), 0); }
public static String des_2(String args) throws Exception { SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec("12345678".getBytes())); AlgorithmParameterSpec iv = new IvParameterSpec("87654321".getBytes()); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(1, secretKey, iv); return Base64.encodeToString(cipher.doFinal(args.getBytes()), 0); } }
|
DES密钥固定8个字节,大于8字节舍弃
DESKeySpec重要的类,其实底层还是调用的SecretKeySpec
RSA,AES,DES,3DES都是用这个cipher类去加密的
DESede
和DES没什么区别就是长度为24的密钥(3倍)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.xiaojianbang.app;
import android.util.Base64; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec;
public class DESede { public static String desede(String args) throws Exception { SecretKey secretKey = SecretKeyFactory.getInstance("DESede").generateSecret(new DESedeKeySpec("123456781234567812345678".getBytes())); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(1, secretKey); cipher.update(args.getBytes()); return Base64.encodeToString(cipher.doFinal("xiaojianbang".getBytes()), 0); } }
|
AES
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.xiaojianbang.app;
import android.util.Base64; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;
public class AES { public static String aes(String args) throws Exception { SecretKeySpec key = new SecretKeySpec("1234567890abcdef1234567890abcdef".getBytes(), "AES"); AlgorithmParameterSpec iv = new IvParameterSpec("1234567890abcdef".getBytes()); Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding"); aes.init(1, key, iv); return Base64.encodeToString(aes.doFinal(args.getBytes("UTF-8")), 0); } }
|
非对称加密算法
RSA
1、使用公钥加密,使用私钥解密
2.公钥是公开的,私钥保密
3、加密处理安全,但是性能极差,单次加密长度有限制
pkcs1padding 明文最大字节数为密钥字节数-11 密文与密钥等长
NoPadding 明文最大字节数为密钥字节数 密文与密钥等长
4、RSA既可用于数据交换,也可用于数据校验
数据校验通常结合消息摘要算法MD5withRSA等
5、两种加密算法常见结合套路
随机生成密钥
密钥用于AES/DES/3DES加密数据
RSA对密钥加密
提交加密后的密钥和加密后的数据给服务器
RSA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| package com.xiaojianbang.app;
import android.util.Base64; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher;
public class RSA { public static String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9xhBZOWWF5Icw384mJksmaJ53RBLPUbEq5hXWW4Xgf82r6Zj24e3MWOnBTcblDodXYtSsaRJilosdTQVWGetJewebKmyqh1l1lUagS1/dbII9GsGat5zMboMHLWUO9NoBS9VDxqYL2VLppNEj/Xe39gBRHIiSnmtggiHuYsEv8wIDAQAB"; public static String priKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJWFpHc6vuy5SXAdSXYvLfq5WZuhnf4eGi+iAOMuBET0JtpSiRLZ6oZpUV9vEBTEVOE0O5er98EP5J1SCmmZxmsjDgcww/gC0TaoklAf8rE9aZtcfsu/70KKw209g6W9Yn8YdGp/3HdMEqON4nYKO5XGU8ENfrf4RyKXYlH2SVVrAgMBAAECgYAJ0TeGOI42nsfKm7GqF9juAGN4y3jDKZjQjdN/FxNir6Epboffe/1hC+My3+jvZCCqlLJg+AKRY4jAJ5XVbypO3tHRd9uLFgCjzREJ09J6SWyNj3KFKCkJ4vpaO0jbUAAtFGlLElc6ZtHNKabeJ0ECOgcIvVsfHpP47j1GTRU8oQJBAMXsksEmrIvCJ0l5mdDX73nRJzbxDK6m7jndE4fBe0h3Wl06iBCfuaS2x+PTjmiRWvfFu2B1/9E9Tt0jc4FQS3ECQQDBZUKZjnv6rKtwqBj1EqjIXVF2SAsttW/6vTpg6mhHYITlrqQqrt1NJ5+6PRVQr1FLDxPArNVSdoz6MFIIAiibAkA+3K+Tt0PQM78koAGRijPePea1lYPQqOY67JN6Z6JPVtEVkTSMCx78SK1eF+BAKAJ7dYrYzUGN5Gn65HqYFLeRAkBcBOFWjSxCjwwX03PkkBdNFtHe9NKU0iLQ7F6tpHsvkyZI3vrv8DoOLw9aHxxYQsLscuUUJWhvD0du97TgaJ6HAkEAoRXjsQO2UmgQcddE2e6Uxp5riOuWIEEzoW6YssCW9BznCnwXy/xamrTKhoW2cIHwn6cFx+MFmyaK5T0xAtF5pw==";
public static PublicKey getPublicKey(String key) throws Exception { byte[] keyBytes = Base64.decode(key, 0); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; }
public static PrivateKey getPrivateKey(String key) throws Exception { byte[] keyBytes = Base64.decode(key, 0); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; }
public static String sign(String data) throws Exception { PrivateKey priK = getPrivateKey(priKey); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initSign(priK); sig.update(data.getBytes()); return Base64.encodeToString(sig.sign(), 0); }
public static boolean verify(byte[] data, byte[] sign) throws Exception { PublicKey pubK = getPublicKey(pubKey); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(pubK); sig.update(data); return sig.verify(sign); }
public static byte[] encrypt(byte[] plaintext) throws Exception { PublicKey publicKey = getPublicKey(pubKey); Cipher cipher = Cipher.getInstance("RSA/None/NoPadding", "BC"); cipher.init(1, publicKey); byte[] bt_encrypted = cipher.doFinal(plaintext); return bt_encrypted; }
public static byte[] decrypt(byte[] encrypted) throws Exception { PrivateKey privateKey = getPrivateKey(priKey); Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC"); cipher.init(2, privateKey); byte[] bt_original = cipher.doFinal(encrypted); return bt_original; }
public static String rsa(String args) throws Exception { byte[] cipher = encrypt("xiaojianbang".getBytes()); return Base64.encodeToString(cipher, 0); } }
|
PKCS填充的话会使得每一次加密数据都不一样
RSA HEX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package com.xiaojianbang.app;
import android.util.Base64; import java.math.BigInteger; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.RSAPublicKeySpec; import javax.crypto.Cipher;
public class RSAHex {
public static String f34N = "a32f7530324569c1d86dec45140c21ae0a6950d5331d22c591ab8c2834ecfbdf51682f494bbc07d17d7ff2b634fd13080954d9e145b6389ca3f23da22d52c1f70fdf716e56868cd7a49c3e8a13c30a18bdfd612d685efe8e36723e15d06446f0de4039a7cae690e96a23a3ba9193d80f1ad3afb1b70a76e2a927dba8fb63d6fb";
public static String f33E = "010001";
public static PublicKey createPublicKey(String stringN, String stringE) throws Exception { BigInteger N = new BigInteger(stringN, 16); BigInteger E = new BigInteger(stringE, 16); RSAPublicKeySpec spec = new RSAPublicKeySpec(N, E); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); }
public static String createPublicKey(String stringN) throws Exception { BigInteger N = new BigInteger(stringN); BigInteger E = new BigInteger("65537"); RSAPublicKeySpec spec = new RSAPublicKeySpec(N, E); KeyFactory kf = KeyFactory.getInstance("RSA"); return Base64.encodeToString(kf.generatePublic(spec).getEncoded(), 0); }
public static byte[] encrypt(String message, PublicKey key) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(1, key); byte[] data = cipher.doFinal(message.getBytes()); return data; }
public static String rsaHex(String args) throws Exception { return Base64.encodeToString(encrypt(args, createPublicKey(f34N, f33E)), 0); } }
|
数字签名验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static String sign(String data) throws Exception { PrivateKey priK = getPrivateKey(priKey); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initSign(priK); sig.update(data.getBytes()); return Base64.encodeToString(sig.sign(), 0); }
public static boolean verify(byte[] data, byte[] sign) throws Exception { PublicKey pubK = getPublicKey(pubKey); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(pubK); sig.update(data); return sig.verify(sign); }
|