DES、AES、RSA加密

加密算法

  1. 单向加密: MD5 SHA
  2. Base64加密
  3. 对称加密: AES (Advanced Encription Standard) \ DES (Data Encryption Standard)
  4. 非对称加密:RSA

MD5 消息摘要算法5

MD5 (Message-Digest Algorithm 5)消息摘要算法5 是一种单向的加密算法,是不可逆的一种加密方式。

1. MD5加密的特点

  • 压缩性:任意长度的数据,计算出来的MD5值都是固定的
  • 容易计算: 从原数据计算出MD5值是非常方便的
  • 抗修改性: 对原数据做任何改动 哪怕之修改1个字节,MD5值都有很大区别
  • 强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(伪造数据)是非常困难的。

2. 应用场景:

  • 文件一致性较验
  • 数组签名
  • 安全访问认证
MD5 加密使用实例
 /**
     * MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法,信息摘要是安全的单项哈西函数,它接收任意大小的数据,并输出固定长度的哈希值
     * @param str
     * @return
     */
    public static String MD5Encode(String str){
        MessageDigest algorithm ;

        String md5 = "";
        try {
            //实例化一个采用MD5算法的 信息摘要
            algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();// 重置摘要 以供使用
            algorithm.update(str.getBytes());//使用bytes更新摘要
            byte[] bytes = algorithm.digest();
            md5 = toHexString(bytes,"");
            Log.d(TAG,"MD5Encode:"+str+",md5:"+md5);
        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }

        return md5;
    }

    public static String toHexString(byte[] bytes,String seperator){

        StringBuffer hexString = new StringBuffer();
        for(byte b:bytes){
            String hex = Integer.toHexString(b&0xff);
            if(hex.length() == 1){
                hexString.append("0");
            }
            hexString.append(hex).append(seperator);
        }
        return hexString.toString();
    }

SHA 安全散列算法 : 也是一种单向的数据加密算法

 /**
     * SHA 安全散列算法
     * @param str
     * @return
     */
    public static String SHAEncode(String str){

        MessageDigest algorithm;
        String sha = "";
        try {
            algorithm = MessageDigest.getInstance("SHA");
            algorithm.reset();
            algorithm.update(str.getBytes());
            byte[] bytes = algorithm.digest();
            sha = toHexString(bytes,"");
        }catch (NoSuchAlgorithmException e){

        }finally {

        }
        Log.d(TAG,"SHAEncode:"+str+",sha:"+sha);
        return sha;
    }

Base64 加密算法

Base64 并不是安全领域的加密算法,只能算是一个编码算法。标准的Base64编码解码无需任何额外的信息即完全可逆。
Base64 编码 本质上是一种将二进制数据转换成文本数据的方案。对于非二进制数据,是先将其转换成二进制形式,然后每连续6个比特(2^6 = 64) 计算其十进制值,根据该值在A-Z、a-z、0-9、+、/ 这64个字符种找到对应的字符,最终得到一个文本串。

  • 标准的Base64只有64个字符(A-Z、a-z、0-9、+、/)以及用作后缀的等号
  • Base64是把3个子节变成4个字符,所以base64编码后的字符串一定能狗被4整除(不算用作后缀的=)
  • 等号一定用作后缀,并且数目一定是0个、1个和2个。这是因为如果原文长度不能被3整除,Base64要在后面添加\0凑齐3n位.为了正确还原,添加了几个\0就加上几个等号。显然添加等号的数目只能是0、1或2;
  • 严格来说Base64不能算一种加密,只能说是编码转换。


    image
public static String base64Encode(String origStr){
        byte[] endcode =  Base64.encode(origStr.getBytes(),Base64.DEFAULT);
        String encodeStr = new String(endcode);
        Log.d(TAG,"origStr:"+origStr+",endcodeStr:"+encodeStr);
        return encodeStr;
    }

    public static String base64Decode(String encodedStr){

        byte[] orign = Base64.decode(encodedStr,Base64.DEFAULT);
        String orignStr = new String(orign);
        return orignStr;
    }
  • 针对Base64.DEFAULT参数说明

DEFAULT 这个参数是默认,使用默认的方法来加密

NO_PADDING 这个参数是略去加密字符串最后的”=”

NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了)

CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LF

URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/

DES加密(Data Encryption Standard) 数据加密标准

  • DES加密算法出自IBM的研究,后来被美国政府采用,之后广为流传。但近年来使用越来越少,因为DES 使用56位密钥,以现代的计算能力,24小时即可破解。
  • DES 使用固定的8个字节(8bytes)作为密钥,初始化向量 也为8bytes

常用常量:

    private final static String HEX = "0123456789ABCDEF";
    private final static String TRANSFORMATION = "DES/CBC/PKCS5Padding";//DES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
    private final static String IVPARAMETERSPEC = "01020304";////初始化向量参数,AES 为16bytes. DES 为8bytes.
    private final static String ALGORITHM = "DES";//DES是加密方式
    private static final String SHA1PRNG = "SHA1PRNG";//// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
// 初始化向量(8字节),随意填充
    private static byte[] iv = { 'a', 'b', 'c', 'd', 'e', 1, 2, '*'};

    /**
     * DES (Data Encryption Standard)  数据标准加密:DES 加密的Key 只能是8byte (8个字节)
     * @param key
     * @param encryptText
     * @return
     */
    public static String DESEncode(String key,String encryptText){
        byte[] keyBytes = key.getBytes();//原始的加密key

        //SecretKeySpec - 为加密后的秘钥
        SecretKeySpec secrectKey = new SecretKeySpec(keyBytes,"DES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

        Cipher cipher = null;
        String output = "";
        try {
            cipher= Cipher.getInstance("DES/CBC/PKCS5Padding");//加密算法/工作方式/?
            cipher.init(Cipher.ENCRYPT_MODE,secrectKey,ivParameterSpec);//指定加密动作 和加密钥
            byte[] encryptData = cipher.doFinal(encryptText.getBytes());
            output = Base64.encodeToString(encryptData,Base64.DEFAULT);

        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }
        return output;
    }

    public static String DESDecode(String key,String decryptString){

        byte[] orginKey = key.getBytes();
        SecretKeySpec secretKeySpec = new SecretKeySpec(orginKey,"DES");

        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

        byte[] base64Decode = Base64.decode(decryptString.getBytes(),Base64.DEFAULT);
        Cipher cipher = null;
        String decodeStr = "";
        try {
            cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec);
            byte[] descrptData = cipher.doFinal(base64Decode);
            decodeStr = new String(descrptData);
        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }
        return decodeStr;
    }
    
    
    测试代码:
        String org = "大漠孤烟直";
      
        String desEncode = EncodeUtils.DESEncode("*()&^%$#",org);
        String desDecode = EncodeUtils.DESDecode("*()&^%$#",desEncode);
        Log.d(TAG,"orig:"+org+",desEncode:"+desEncode+",desDecode:"+desDecode);

DES的扩展 3DES

3DES是DES加密算法的一种模式,它使用3条64位的密钥对数据进行三次加密。
3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),是DES的一个更安全的变形。

AES (Advanced Encryption Standard) 高级加密标准。AES 本身就是为了取代DES的,AES 具有更好的安全性、效率和灵活性。

/**
     * 真正的加密过程
     * 1.通过密钥得到一个密钥专用的对象SecretKeySpec
     * 2.Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用写算法然后用默认的其他方式)Cipher.getInstance("AES");
     * @param key
     * @param str
     * @return
     */
    public static String AESEncode(String key,String str){
        String result = "";
        SecretKeySpec secretKeySpec = new SecretKeySpec(generateKey(key),"AES");
        try {
            Cipher cipher = Cipher.getInstance("AES");//生成Cipher
            cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,new IvParameterSpec(new byte[cipher.getBlockSize()]));
            byte[] encrypted = cipher.doFinal(str.getBytes());
            result = toHexString(encrypted,"");
        }catch (Exception e){

        }finally {

        }
        return result;
    }


    /**
     * 生成 128、192、256位 秘钥
     * @param rawKey
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte[] generateKey(String rawKey){
        //秘钥生成器
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(rawKey.getBytes());
            keyGenerator.init(128,sr);
            SecretKey sKey = keyGenerator.generateKey();
            byte[] mKey = sKey.getEncoded();
            return mKey;
        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }
        return null;
    }


    public static String AESDecode(String key_seed,String encrypedStr){

        byte[] rawData = toByte(encrypedStr);
        String result = "";
        SecretKeySpec secretKeySpec = new SecretKeySpec(generateKey(key_seed),"AES");
        try {
            Cipher cipher = Cipher.getInstance("AES");//生成Cipher
            cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,new IvParameterSpec(new byte[cipher.getBlockSize()]));
            byte[] decrypted = cipher.doFinal(rawData);
            result = new String(decrypted);
        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }
        return result;


    }

    // 将十六进制字符串为十进制字符串
    private static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    // 将十六进制字符串为十进制字节数组
    private static byte[] toByte(String hex) {
        int len = hex.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++) {
            result[i] = Integer.valueOf(hex.substring(2 * i, 2 * i + 2), 16)
                    .byteValue();
        }
        return result;
    }

RSA 为非对称加密

RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥。
RSA算法原理如下:

1.随机选择两个大质数p和q,p不等于q,计算N=pq;
2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素。
3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) 。
4.销毁p和q。

RSA的安全性依赖于大数分解,小于1024为的 N 被证明是不安全的,而且由于RSA算法进行的搜时大数计算,使得RSA最快的情况也比DES慢上倍,这是RSA最大的缺陷。因此通常只能用于加密少量数据或者加密密钥,但RSA仍然不失为一种高强度的算法。

如何使用RSA呢?

  • 第一步 生成秘钥对。
  /**
     * 随机生成RSA密钥对
     *
     * @param keyLength 密钥长度,范围:512~2048
     *                  一般1024
     * @return
     */
    public static KeyPair generateRSAKeyPair(int keyLength) {
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
            kpg.initialize(keyLength);
            return kpg.genKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
  • 第二步 使用公钥加密 使用秘钥解密 或者使用秘钥加密、公钥解密。
    /**
     * 私钥加密
     *
     * @param data       待加密数据
     * @param privateKey 密钥
     * @return byte[] 加密数据
     */
    public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
        // 得到私钥
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
        return cipher.doFinal(data);
    }

/**
     * 公钥解密
     *
     * @param data      待解密数据
     * @param publicKey 密钥
     * @return byte[] 解密数据
     */
    public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
        // 得到公钥
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 数据解密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, keyPublic);
        return cipher.doFinal(data);
    }
/**
     * 私钥加密
     *
     * @param data       待加密数据
     * @param privateKey 密钥
     * @return byte[] 加密数据
     */
    public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
        // 得到私钥
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
        return cipher.doFinal(data);
    }
/**
     * 使用私钥进行解密
     */
    public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
        // 得到私钥
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);

        // 解密数据
        Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.DECRYPT_MODE, keyPrivate);
        byte[] arr = cp.doFinal(encrypted);
        return arr;
    }

测试代码:



        KeyPair keyPair = EncodeUtils.generateRSAKeyPair(DEFAULT_KEY_SIZE);
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();

        try {
            byte[]encrypteBytes = EncodeUtils.encryptByPublicKey(org.getBytes(),publicKey.getEncoded());
//            String encryptStr = EncodeUtils.base64Encode(encrypteBytes);
            byte[]base64Bytes  = Base64.encode(encrypteBytes,Base64.DEFAULT);

            String encodeStr = new String(base64Bytes);



            byte [] tmp = Base64.decode(encodeStr,Base64.DEFAULT);
            byte[]decryptBytes = EncodeUtils.decryptByPrivateKey(tmp,privateKey.getEncoded());
            String decodeStr = new String(decryptBytes);
            Log.d(TAG,"org:"+org+",encodeStr:"+encodeStr+",decodeStr:"+decodeStr);


        }catch (Exception e){
            e.printStackTrace();
        }

    }

参考链接:
http://www.cnblogs.com/whoislcj/p/5887859.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容