加密算法

来源:互联网 发布:idc数据机房 编辑:程序博客网 时间:2024/06/06 12:58

1、简单的加密(凯撒密码)

基本思想是:通过把字母移动一定的位数来实现加密和解密。明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是 3 的时候,所有的字母 A 将被替换成 D,B 变成 E,由此可见,位数就是凯撒密码加密和解密的密钥。

static int key = 6;/** * 加密 */private static String encrypt(String originalText, int key) {// 把所有的字符向右移char[] cs = originalText.toCharArray();for (int i = 0; i < cs.length; i++) {// 转化成asci码int asci = cs[i];char newChar = (char) (asci + key);cs[i] = newChar;}return new String(cs);}/** * 解密 */private static String decrypt(String originalText, int key) {// 把所有的字符向左移char[] cs = originalText.toCharArray();for (int i = 0; i < cs.length; i++) {// 转化成asci码int asci = cs[i];char newChar = (char) (asci - key);cs[i] = newChar;}return new String(cs);}
String originalText = "Hello World";String encrypt = encrypt(originalText,key);System.out.println("加密后:"+encrypt);String decrypt = decrypt(encrypt, key);System.out.println("解密后:"+decrypt);
结果:

2、对称加密

加密和解密都使用同一把秘钥,这种加密方法称为对称加密,也称为单密钥加密。

对称加密常用算法:AES、DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK 等。

DES加密:

String originalText = "Hello World";// 创建一个加密器Cipher cipher = null;try {cipher = Cipher.getInstance("DES");Key key = KeyGenerator.getInstance("DES").generateKey();// 设置加密器是解密还是加密cipher.init(Cipher.ENCRYPT_MODE, key);// 加密方法byte[] encrypt = cipher.doFinal(originalText.getBytes());System.out.println("加密后:" + new String(encrypt));// 解密cipher.init(Cipher.DECRYPT_MODE, key);byte[] decrypt = cipher.doFinal(encrypt);System.out.println("解密后:" + new String(decrypt));} catch (Exception e) {e.printStackTrace();}
结果:

但是此时key值一直在变化,相同内容,每次加密的结果不一样,处理办法是可以保存唯一使用同一个key值。

DES自定义key

private static String ALGORITHM = "DES";static String textKey = "123456787777";// des密钥的长度是64位,其中56位参数加密,8位做校验,如果密钥长度大于64,64位后的字符都不无效的String originalText = "Hello World";// 生成加密器Cipher cipher = Cipher.getInstance(ALGORITHM);DESKeySpec keySpec = new DESKeySpec(textKey.getBytes());// 密钥工厂SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);Key key = keyFactory.generateSecret(keySpec);// 设置操作模式cipher.init(Cipher.ENCRYPT_MODE, key);byte[] encrypt = cipher.doFinal(originalText.getBytes());// 解密cipher.init(Cipher.DECRYPT_MODE, key);byte[] decrypt = cipher.doFinal(encrypt);System.out.println(new String(decrypt));
AES自定义key

private static String KEY_ALGORITHM = "AES";private static String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//算法/工作模式/填充模式static String textKey = "1234567812345678";// aes密钥的长度是128位String originalText = "Hello World";//加密String encrypt = encrypt(originalText, textKey);System.out.println("加密后:"+encrypt);String decrypt = decrypt(encrypt, textKey);System.out.println("解密后:"+decrypt);private static String encrypt(String text,String key){String encryptStr = null;try {//获取加密器Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//获取自定义的keySecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), KEY_ALGORITHM);//初始化操作模式cipher.init(Cipher.ENCRYPT_MODE, keySpec);//加密后字节数组byte[] encrypt = cipher.doFinal(text.getBytes());//这个地方不能直接创建字符串返回//encryptStr = new String(encrypt);//用Base64编码一下encryptStr = Base64.encode(encrypt);} catch (Exception e) {e.printStackTrace();}return encryptStr;}private static String decrypt(String text,String key){String encryptStr = null;try {Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), KEY_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, keySpec);//Base64解码一下byte[] decode = Base64.decode(text);//解密byte[] encrypt = cipher.doFinal(decode);encryptStr = new String(encrypt);} catch (Exception e) {e.printStackTrace();}return encryptStr;}
3、非对称加密

非对称加密算法需要两个密钥:公钥(publickey)和私钥(privatekey)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密;如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
简单理解为:加密和解密是不同的钥匙

常见算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。

RSA加密解密:

private static String algorithm = "RSA";// 公钥加密私钥解密,私钥加密公钥解密private static int ENCRYPT_LENTH = 117;// 加密时数据长度不能超过117private static int DECRYPT_LENTH = 128;// 解密时数据长度不能超过128String originalText = "Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World";// 生成公钥和私钥,密钥不能够自定义// 密钥对生成器KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance(algorithm);// 生成密钥对KeyPair keyPair = pairGenerator.genKeyPair();// 获取公钥PublicKey publicKey = keyPair.getPublic();// 获取私钥PrivateKey privateKey = keyPair.getPrivate();// 公钥加密// 生成加密器Cipher cipher = Cipher.getInstance(algorithm);cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] bytes = originalText.getBytes();//分块加解密byte[] encrypt = doCrypt(cipher, bytes,ENCRYPT_LENTH);// 私钥解密cipher.init(Cipher.DECRYPT_MODE, privateKey);//byte[] decrypt = cipher.doFinal(encrypt);byte[] decrypt = doCrypt(cipher, encrypt,DECRYPT_LENTH);System.out.println(new String(decrypt));private static byte[] doCrypt(Cipher cipher, byte[] bytes,int cryptLength)throws IllegalBlockSizeException, BadPaddingException, IOException {int length = bytes.length;// 200int offSet = 0;byte[] tmp = null;//字节数组的拼接ByteArrayOutputStream bos = new ByteArrayOutputStream();while ((length - offSet) > 0) {//分块加密if (length - offSet >= cryptLength) {tmp = cipher.doFinal(bytes, offSet, cryptLength);}else{tmp = cipher.doFinal(bytes, offSet, length - offSet);}offSet += cryptLength;bos.write(tmp);}//加密后的字节数组byte[] encrypt = bos.toByteArray();return encrypt;}
4、消息摘要

常见算法MD5、SHA、CRC 等。

String text = "Hello World";//MD5,SHAMessageDigest digest = MessageDigest.getInstance("MD5");//消息摘要的字节数组byte[] msg = digest.digest(text.getBytes());//将数组转化字符String msgText = Hex.encode(msg);System.out.println(msgText);//b10a8db164e0754105b7a99be72e3fe5          MD5//0a4d55a8d778e5022fab701977c5d840bbc486d0  SHA

MD5一种数据摘要算法, 可以将任何文件或者字符串,加密成为一个32位长度的特征码, 数字指纹, 数字摘要(秒传),不可逆, 无法通过md5还原文件或字符串
MD5破解: 通过海量数据库进行暴力破解

5、数字签名

数字签名是非对称加密与数字摘要的组合应用。

//私钥加密(签名),用我的公钥能解开,说明这确实是我签名//MD2withRSA MD5withRSA SHA1withRSAString text = "我借了你100W";//先对原文进行MD5,再对MD5后的结果进行RSA加密Signature signature = Signature.getInstance("MD5withRSA");// 密钥对生成器KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance("RSA");// 生成密钥对KeyPair keyPair = pairGenerator.genKeyPair();// 获取公钥PublicKey publicKey = keyPair.getPublic();// 获取私钥PrivateKey privateKey = keyPair.getPrivate();//签名signature.initSign(privateKey);//输入原文signature.update(text.getBytes());//进行签名byte[] sign = signature.sign();//验证签名signature.initVerify(publicKey);//输入原文signature.update(text.getBytes());//验签boolean verify = signature.verify(sign);System.out.println(verify);
6、Https

SSLContext context = SSLContext.getInstance("SSL");//SSL TLS//信任管理器数组TrustManager[] tm = new TrustManager[]{new EmptyTrustManager()};//初始化SSL上下文context.init(null, tm, null);String urlStr = "https://kyfw.12306.cn/otn/";//设置信任管理器,需要在连接前就设置好HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());URL url = new URL(urlStr);HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();//获取流对象InputStream is = connection.getInputStream();String str = Util.inputStream2String(is);System.out.println(str);static class EmptyTrustManager implements X509TrustManager{@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {// TODO Auto-generated method stub}@Overridepublic X509Certificate[] getAcceptedIssuers() {// TODO Auto-generated method stubreturn null;}}

SSLContext context = SSLContext.getInstance("SSL");//SSL TLS//导入证书Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(new File("srca.cer")));//创建密钥库KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());//初始化密钥库keyStore.load(null);//将证书放入密钥库keyStore.setCertificateEntry("srca", certificate);//信任管理器的工厂TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());//将密钥库放入密钥工厂中trustManagerFactory.init(keyStore);//获取信任管理器数组TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();//初始化SSL上下文context.init(null, trustManagers, null);String urlStr = "https://kyfw.12306.cn/otn/";//设置信任管理器,需要在连接前就设置好HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());URL url = new URL(urlStr);HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();//获取流对象InputStream is = connection.getInputStream();String str = Util.inputStream2String(is);System.out.println(str);

Util

public class Util {//https://kyfw.12306.cn/otn/// 英文里出现次数最多的字符private static final char MAGIC_CHAR = 'e';// 破解生成的最大文件数private static final int DE_MAX_FILE = 4;public static String file2String(String path) throws IOException {FileReader reader = new FileReader(new File(path));char[] buffer = new char[1024];int len = -1;StringBuffer sb = new StringBuffer();while ((len = reader.read(buffer)) != -1) {sb.append(buffer, 0, len);}return sb.toString();}public static void string2File(String data, String path) {FileWriter writer = null;try {writer = new FileWriter(new File(path));writer.write(data);} catch (Exception e) {e.printStackTrace();} finally {if (writer != null) {try {writer.close();} catch (IOException e) {e.printStackTrace();}}}}public static String inputStream2String(InputStream in) throws IOException {int len = -1;byte[] buffer = new byte[1024];ByteArrayOutputStream baos = new ByteArrayOutputStream();while ((len = in.read(buffer)) != -1) {baos.write(buffer, 0, len);}baos.close();return baos.toString("UTF-8");}public static void printCharCount(String path) throws IOException {String data = Util.file2String(path);List<Entry<Character, Integer>> mapList = getMaxCountChar(data);for (Entry<Character, Integer> entry : mapList) {// 输出前几位的统计信息System.out.println("字符'" + entry.getKey() + "'出现"+ entry.getValue() + "次");}}public static void encryptFile(String srcFile, String destFile, int key)throws IOException {String artile = Util.file2String(srcFile);// 加密文件String encryptData = encrypt(artile, key);// 保存加密后的文件Util.string2File(encryptData, destFile);}public static void decryptCaesarCode(String input, String destPath) {int deCount = 0;// 当前解密生成的备选文件数// 获取出现频率最高的字符信息(出现次数越多越靠前)List<Entry<Character, Integer>> mapList = getMaxCountChar(input);for (Entry<Character, Integer> entry : mapList) {// 限制解密文件备选数if (deCount >= DE_MAX_FILE) {break;}// 输出前几位的统计信息System.out.println("字符'" + entry.getKey() + "'出现"+ entry.getValue() + "次");++deCount;// 出现次数最高的字符跟MAGIC_CHAR的偏移量即为秘钥int key = entry.getKey() - MAGIC_CHAR;System.out.println("猜测key = " + key + ", 解密生成第" + deCount + "个备选文件"+ "\n");String decrypt = decrypt(input, key);String fileName = "de_" + deCount + destPath;Util.string2File(decrypt, fileName);}}// 统计String里出现最多的字符public static List<Entry<Character, Integer>> getMaxCountChar(String data) {Map<Character, Integer> map = new HashMap<Character, Integer>();char[] array = data.toCharArray();for (char c : array) {if (!map.containsKey(c)) {map.put(c, 1);} else {Integer count = map.get(c);map.put(c, count + 1);}}// 获取获取最大值int maxCount = 0;for (Entry<Character, Integer> entry : map.entrySet()) {// 不统计空格if (/* entry.getKey() != ' ' && */entry.getValue() > maxCount) {maxCount = entry.getValue();}}// map转换成list便于排序List<Entry<Character, Integer>> mapList = new ArrayList<Map.Entry<Character, Integer>>(map.entrySet());// 根据字符出现次数排序Collections.sort(mapList, new Comparator<Entry<Character, Integer>>() {@Overridepublic int compare(Entry<Character, Integer> o1,Entry<Character, Integer> o2) {return o2.getValue().compareTo(o1.getValue());}});return mapList;}public static String encrypt(String input, int key) {char[] array = input.toCharArray();for (int i = 0; i < array.length; i++) {// 字符转为acsii码值int ascii = array[i];// 字符偏移ascii = ascii + key;// ascii码值转换为对应字符char newChar = (char) ascii;// 替换原有字符array[i] = newChar;// 以上4行代码可以简写为一行// array[i] = (char) (array[i] + 1);}return new String(array);}public static String decrypt(String input, int key) {char[] array = input.toCharArray();for (int i = 0; i < array.length; i++) {// 字符转为acsii码值int ascii = array[i];// 字符偏移ascii = ascii - key;// ascii码值转换为对应字符char newChar = (char) ascii;// 替换原有字符array[i] = newChar;// 以上4行代码可以简写为一行// array[i] = (char) (array[i] + 1);}return new String(array);}}
Android里的https请求:

把scra.cer文件考到assets或raw目录下,或者直接使用证书的RFC格式,接下来的做法和java工程代码一样。

Base64

import java.io.*;     public class Base64 {       private static char[] base64EncodeChars = new char[] {           'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',           'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',           'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',           'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',           'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',           'o', 'p', 'q', 'r', 's', 't', 'u', 'v',           'w', 'x', 'y', 'z', '0', '1', '2', '3',           '4', '5', '6', '7', '8', '9', '+', '/' };           private static byte[] base64DecodeChars = new byte[] {       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,       -1,  0,  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, -1, -1, -1, -1, -1,       -1, 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, -1, -1, -1, -1, -1 };           public static String encode(byte[] data) {           StringBuffer sb = new StringBuffer();           int len = data.length;           int i = 0;           int b1, b2, b3;           while (i < len) {               b1 = data[i++] & 0xff;               if (i == len)               {                   sb.append(base64EncodeChars[b1 >>> 2]);                   sb.append(base64EncodeChars[(b1 & 0x3) << 4]);                   sb.append("==");                   break;               }               b2 = data[i++] & 0xff;               if (i == len)               {                   sb.append(base64EncodeChars[b1 >>> 2]);                   sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);                   sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);                   sb.append("=");                   break;               }               b3 = data[i++] & 0xff;               sb.append(base64EncodeChars[b1 >>> 2]);               sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);               sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);               sb.append(base64EncodeChars[b3 & 0x3f]);           }           return sb.toString();       }           public static byte[] decode(String str) throws UnsupportedEncodingException {           StringBuffer sb = new StringBuffer();           byte[] data = str.getBytes("US-ASCII");           int len = data.length;           int i = 0;           int b1, b2, b3, b4;           while (i < len) {               /* b1 */               do {                   b1 = base64DecodeChars[data[i++]];               } while (i < len && b1 == -1);               if (b1 == -1) break;               /* b2 */               do {                   b2 = base64DecodeChars[data[i++]];               } while (i < len && b2 == -1);               if (b2 == -1) break;               sb.append((char)((b1 << 2) | ((b2 & 0x30) >>> 4)));               /* b3 */               do {                   b3 = data[i++];                   if (b3 == 61) return sb.toString().getBytes("ISO-8859-1");                   b3 = base64DecodeChars[b3];               } while (i < len && b3 == -1);               if (b3 == -1) break;               sb.append((char)(((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));               /* b4 */               do {                   b4 = data[i++];                   if (b4 == 61) return sb.toString().getBytes("ISO-8859-1");                   b4 = base64DecodeChars[b4];               } while (i < len && b4 == -1);               if (b4 == -1) break;               sb.append((char)(((b3 & 0x03) << 6) | b4));           }           return sb.toString().getBytes("ISO-8859-1");       }   }   
Hex
/** * 字节数组与16进制字符串转换工具 */public class Hex {private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6','7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };/** * 字节数组转换成16进制字符串 *  * @param bytes * @return */public static String encode(byte[] bytes) {if (bytes == null || bytes.length == 0) {return null;}StringBuffer sb = new StringBuffer(bytes.length * 2);// 27对应的十六进制为1b,对应的二进制是00011011// 取高位和低位:00011011-》0001,1011-》1,bfor (int i = 0; i < bytes.length; ++i) {// 取高位:跟0xf0做与运算后再右移4位int high = (bytes[i] & 0xf0) >> 4;// 0xf0: 11110000// 取低位:跟0x0f做与运算int low = bytes[i] & 0x0f;// 0x0f: 00001111// 字符映射sb.append(HEX_CHAR[high]).append(HEX_CHAR[low]);}return sb.toString();}/** * 16进制字符串转换为字节数组 *  * @param hex *            16进制字符 * @return */public static byte[] decode(String hex) {if (hex == null || hex.length() == 0) {return null;}// 16进制转byte,长度减半,"1b"-->27int len = hex.length() / 2;byte[] result = new byte[len];String highStr = null;String lowStr = null;int high = 0;int low = 0;for (int i = 0; i < len; i++) {// 高位值highStr = hex.substring(i * 2, i * 2 + 1);// "1b"的高位为"1"high = Integer.parseInt(highStr, 16);// 高位转为10进制// 低位值lowStr = hex.substring(i * 2 + 1, i * 2 + 2);// "1b"的低位为"b"low = Integer.parseInt(lowStr, 16);// 低位转为10进制// 合计值result[i] = (byte) ((high << 4) + low);// 相当于:(高位*16) + 低位}return result;}}


0 0
原创粉丝点击