常用加解密及摘要算法介绍及使用场景–MD5,SHA1,AES,DES,3DES,RSA,ECC

 加解密  常用加解密及摘要算法介绍及使用场景–MD5,SHA1,AES,DES,3DES,RSA,ECC已关闭评论
10月 292020
 

网上看到的一篇常用加解密算法、摘要算法的介绍文章,转载来自CSDN

数字签名信息加密是前后端开发经常使用的技术。应用场景包括:用户登录,交易,信息通讯等。

1、数字签名

数字签名 简单来说就是通过提供可鉴别 的数字信息 验证自身身份的一种方式。

一套 数字签名 通常定义两种 互补的运算,一个用于签名,另一个用于验证,分别  发送者持有能够代表自己的私钥,由接受者持有的与私钥对应的公钥,能够在接受到来自发送者信息时候用于验证其身份。

2、加密和解密

2.1 加密: 数据加密 基本过程,就是对来的铭文的文件或者数据 按照 某种算法 进行处理,使其成为不可读的一段代码,通常成为 “密文”。通过这样的途径,来达到保护数据 不被别人 非法窃取,阅读的目的。

2.2 解密:加密的逆过程为解密,将 编码的信息 转为为 原有的数据 的过程。

3、对称加密和非对称加密

面试相关问题:举例说一下有哪些常用的对称算法?及其使用场景。
常见的对称加密算法:DES3DESAES

常见的非对称加密算法:RSADSA

散列算法:SHA-1MD5等,其应用场景?

3.1、对称加密(共享密钥加密算法)

在对称加密算法中,使用的密钥只有一个,发送者  接受者 双方都是用这一个密钥进行 加密  解密。这就要求通信双方都必须事先知道这个密钥。

  • 数据加密过程:在对称加密算法中,数据发送方  明文 和加密密钥 一起经过特殊加密处理,生成 密文 进行发送。
  • 数据解密过程:数据接收方,收到密文后,若想读取原数据,则需要使用加密使用的密钥 即相同算法的 逆算法 对密文进行解密,才可以恢复到 可读的明文。

3.2、非对称加密算法(公开密钥加密算法)

在非对称加密算法中,她需要两个密钥,一个称为公开密钥,另一个为私有密钥。因为加密和解密使用的密钥不同,所以称为非对称加密算法。

  • 如果使用公钥对数据进行加密,只有用对应的私钥才可以对其进行解密。
  • 如果使用私钥对数据进行加密,只有用对应的公钥才可以对其进行解密。

4、常用的签名加密算法

4.1MD5算法 (相比于SHA1 安全性低,但是 速度快)

MD5算法用的是哈希函数,他的典型应用是对于一段信息产生信息摘要,以防止被篡改。严格来说MD5不算一种加密算法,而是一种 摘要算法。无论多长的输入,MD5都会输出长度为128bits的一个串(通常用16进制表示32个字符)。


public class MD5 {

    public static final byte[] computeMD5(byte[] content) {

        try {

            MessageDigest md5 = MessageDigest.getInstance(“MD5”);

            return md5.digest(content);

        } catch (NoSuchAlgorithmException e) {

            throw new RuntimeException(e);

        }

    }



    public static void main(String[] args) {

        String s1 = “hello world”;

        byte[] bytes = s1.getBytes();

        System.out.println(s1 +加密后的密文为:+computeMD5(bytes));

    }

}


// 输出结果:hello world经过MD5加密后的密文为:[[email protected]

 

4.2 SHA1算法 (相比于MD5 安全性高,但是 速度慢)

SHA1算法和MD5算法是一样流行 消息摘要算法,然而SHA1的安全性会高于MD5。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。


public class SHA1 {
    public static byte[] computeSHA1(byte[] content) {

        try {

            MessageDigest sha1 = MessageDigest.getInstance(“SHA1”);

            return sha1.digest(content);

        } catch (NoSuchAlgorithmException e) {

            throw new RuntimeException(e);

        }

    }



    public static void main(String[] args) {

        String s1 = “hello world”;

        byte[] bytes = s1.getBytes();

        System.out.println(s1 +加密后的密文为:+computeSHA1(bytes));

    }

}


// 输出结果:hello world经过SHA1加密后的密文为:[[email protected]

 

根据MD5SHA1的信息摘要及不可逆的特性,应用场景有 

  • 密码验证:服务器端存储用户密码加密后的内容,每次密码校验比较的是密文是否相同,确保服务器管理员也无法获取到用户使用的密码。
  • 文件的完整性比较:当下载一个文件时,服务器返回的信息中包括这个文件的MD5(或者SHA1),在本地下载完毕将其进行MD5加密,之后比较两个MD5只进行比较,如果一直则说明文件完整不存在丢包现象。
  • 文件上传:在上传文件信息的时候,将该文件的MD5同时上传给服务器。服务器中存储了这个文件MD5,并存储这个MD5只对应的已上传的字节长度,比如未上传为0,已完成为-1,已上传200自己,则值为200。可以用于匹配该文件在服务器中的状态,方便断点再传。只要源文件没有改,就算文件改了名字,换个账户都可以在服务器中找到对应的文件,避免存储多份相同文件,并可以提高二次上传时的速度。
  • 版权验证:当一个视频或者音创作出来的时候他的MD5是唯一的,翻录过后的版本的MD5会不同,可以用于版权验证。

4.3 HMAC算法

是一个密钥相关的 哈希运算消息认证码,HMAC运算利用 哈希算法(MD5SHA1等),以一个密钥  一个消息作为输入,生成一个消息摘要 作为输出。HMAC 发送方和接收方都有这个key进行计算,而没有这个key的第三方,则无法计算出正确的散列值,这样就可以防止数据被篡改。 该算法在多线程环境下是不安全的。

对称算法和非对称算法:

4.4 对称算法——AES/DES/3DES算法

AES/DES/3DES 都是对称的块加密算法,加解密过程是可逆的,

4.4.1 AES算法

AES加密算法是密码学中的高级加密标准,该加密算法采用的是 对称分组密码体制,密钥长度最少支持 128位,192位,256位,因而有AES128AES192AES256等常用的加密方式。分组长度为128位,算法更易于各种硬件和软件的实现。

AES本身就是为了取代DES的,AES具有更好的安全性,效率和灵活性。

4.4.2 DES算法

DES加密算法是一种 分组密码,以64位位 分组对数据加密,他的密钥长度是56位,加密和解密用同一个算法。
DES加密算法对于密钥进行保密,而公开算法,包括加密和解密算法。这样只有掌握了和发送方 相同密钥的人才能来解读由DES进行加密的密文数据。

4.4.3 3DES算法

是基于DES的对称算法,对 一块数据  三个不同的密钥 进行三次加密,安全性更高。
 

4.5 非对称算法——RSAECC算法

4.5.1 RSA算法

RSA算法是目前最具影响力的公钥加密算法。RSA是第一个同事用于加密和数字签名的算法,它能够抵抗到目前为止已知的所有密码攻击

RSA算法基于一个十分简单的数论试试,将两个大素数相乘十分容易,但是想要对乘积进行因式分解确十分困难,因此可以将乘积公开作为加密密钥。

4.5.2 ECC算法

ECC算法的主要优势是,在某一些情况下,它可以生成比其他方法更小的密钥,比如RSA算法,并提供相当或者更高级别的安全等级。不过他的缺点是 加密和解密操作的实现会比其他机制时间要长,对于CPU的消耗严重。

utm   详细X
基本翻译
abbr. 统一威胁管理(Unified Threat Management);通用横墨卡托投影(Universal Transverse Mercator projection)
网络释义
UTM: 统一威胁管理
UTM UTM: 统一威胁管理
UTM-: 通用横向墨卡托图

RSA加密解密及数字签名的Java实现

 加解密  RSA加密解密及数字签名的Java实现已关闭评论
6月 132016
 

这篇文章也不错,收藏备用,来源:http://my.oschina.net/jiangli0502/blog/171263


  RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

    RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法

    RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。

    关于RSA算法的原理,这里就不再详加介绍,网上各种资源一大堆。下面就开始介绍RSA加密解密JAVA类的具体实现。

import java.security.MessageDigest; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class Coder { public static final String KEY_SHA="SHA"; public static final String KEY_MD5="MD5"; /**
     * BASE64解密
     * @param key
     * @return  * @throws Exception
     */ public static byte[] decryptBASE64(String key) throws Exception{ return (new BASE64Decoder()).decodeBuffer(key);
    } /**
     * BASE64加密
     * @param key
     * @return  * @throws Exception
     */ public static String encryptBASE64(byte[] key)throws Exception{ return (new BASE64Encoder()).encodeBuffer(key);
    } /**
     * MD5加密
     * @param data
     * @return  * @throws Exception
     */ public static byte[] encryptMD5(byte[] data)throws Exception{
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data); return md5.digest();
    } /**
     * SHA加密
     * @param data
     * @return  * @throws Exception
     */ public static byte[] encryptSHA(byte[] data)throws Exception{
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data); return sha.digest();
    }
}

     先提供Coder编码类,该类封装了基本的Base64、md5和SHA加密解密算法。Java对这些算法的实现提供了很好的API封装,开发人员只需调用这些API就可很简单方便的实现数据的加密与解密。

    下面提供RSA加密解密类,该类为Coder类子类,因为其中对RSA公私密钥的保存进行了一层Base64加密处理。

    RSA加密解密类静态常量

       public static final String KEY_ALGORTHM="RSA";// public static final String SIGNATURE_ALGORITHM="MD5withRSA"; public static final String PUBLIC_KEY = "RSAPublicKey";//公钥 public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥

    RSA加密解密的实现,需要有一对公私密钥,公私密钥的初始化如下:

/**
     * 初始化密钥
     * @return
     * @throws Exception
     */ public static Map<String,Object> initKey()throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair(); //公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); //私钥 RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
        
        Map<String,Object> keyMap = new HashMap<StringObject>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey); return keyMap;
    }

      从代码中可以看出密钥的初始化长度为1024位,密钥的长度越长,安全性就越好,但是加密解密所用的时间就会越多。而一次能加密的密文长度也与密钥的长度成正比。一次能加密的密文长度为:密钥的长度/8-11。所以1024bit长度的密钥一次可以加密的密文为1024/8-11=117bit。所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。对于小文件可以使用RSA加密,但加密过程仍可能会使用分段加密。

    从map中获取公钥、私钥

/**  * 取得公钥,并转化为String类型
     * @param keyMap  * @return  * @throws Exception  */
    public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
        Key key = (Key) keyMap.get(PUBLIC_KEY);  
        return encryptBASE64(key.getEncoded());     
    }

    /**  * 取得私钥,并转化为String类型
     * @param keyMap  * @return  * @throws Exception  */
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
        Key key = (Key) keyMap.get(PRIVATE_KEY);  
        return encryptBASE64(key.getEncoded());     
    }

    对于RSA产生的公钥、私钥,我们可以有两种方式可以对信息进行加密解密。私钥加密-公钥解密 和 公钥加密-私钥解密。
 

    私钥加密

/**
     * 用私钥加密
     * @param data	加密数据
     * @param key	密钥
     * @return  * @throws Exception
     */ public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{ //解密密钥 byte[] keyBytes = decryptBASE64(key); //取私钥 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data);
    }

    私钥解密

/**
     * 用私钥解密 * @param data 	加密数据  * @param key	密钥
     * @return
     * @throws Exception  */
    public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
        //对私钥解密 byte[] keyBytes = decryptBASE64(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODEprivateKey); return cipher.doFinal(data);
    }

    公钥加密

/**
     * 用公钥加密
     * @param data	加密数据
     * @param key	密钥
     * @return  * @throws Exception
     */ public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{ //对公钥解密 byte[] keyBytes = decryptBASE64(key); //取公钥 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data);
    }

    私钥加密

/**
     * 用公钥解密
     * @param data 加密数据  * @param key	密钥
     * @return
     * @throws Exception  */
    public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{
        //对私钥解密 byte[] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        
        //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODEpublicKey); return cipher.doFinal(data);
    }

    关于数字签名,先了解下何为数字签名。数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。数字签名是非对称密钥加密技术与数字摘要技术的应用。简单地说,所谓数字签名就是附加在数据单元上的一些数据,或是对数据单元所作的密码变换。这种数据或变换允许数据单元的接收者用以确认数据单元的来源和数据单元的完整性并保护数据,防止被人(例如接收者)进行伪造。

    数字签名的主要功能如下:
 

    保证信息传输的完整性、发送者的身份认证、防止交易中的抵赖发生。

    数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。

    数字签名是个加密的过程,数字签名验证是个解密的过程。

     数字签名算法依靠公钥加密技术来实现的。在公钥加密技术里,每一个使用者有一对密钥:一把公钥和一把私钥。公钥可以自由发布,但私钥则秘密保存;还有一个要求就是要让通过公钥推算出私钥的做法不可能实现。

    普通的数字签名算法包括三种算法:

    1.密码生成算法;

    2.标记算法;

   3.验证算法

    通过RSA加密解密算法,我们可以实现数字签名的功能。我们可以用私钥对信息生成数字签名,再用公钥来校验数字签名,当然也可以反过来公钥签名,私钥校验。

    私钥签名
 

/**
     *	用私钥对信息生成数字签名
     * @param data	//加密数据
     * @param privateKey	//私钥
     * @return  * @throws Exception
     */ public static String sign(byte[] data,String privateKey)throws Exception{ //解密私钥 byte[] keyBytes = decryptBASE64(privateKey); //构造PKCS8EncodedKeySpec对象 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); //指定加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); //取私钥匙对象 PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //用私钥对信息生成数字签名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey2);
        signature.update(data); return encryptBASE64(signature.sign());
    }

    公钥校验 

/**
     * 校验数字签名
     * @param data	加密数据
     * @param publicKey	公钥
     * @param sign	数字签名
     * @return  * @throws Exception
     */ public static boolean verify(byte[] data,String publicKey,String sign)throws Exception{ //解密公钥 byte[] keyBytes = decryptBASE64(publicKey); //构造X509EncodedKeySpec对象 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); //指定加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); //取公钥匙对象 PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
        
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey2);
        signature.update(data); //验证签名是否正常 return signature.verify(decryptBASE64(sign));
        
    }
9月 162015
 

网上的加密解密系列文章

Java  加密解密基础

密码学是研究编制密码和破译密码的技术科学。研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学;应用于破译密码以获取通信情报的,称为破译学,总称密码学。

 

密码学常用术语

 

明文: 待加密数据。

密文: 明文经过加密后数据。

加密: 将明文转换为密文的过程。

加密算法: 将明文转换为密文的转换算法。

加密密钥: 通过加密算法进行加密操作的密钥。

解密: 将密文转换为铭文的过程。

解密算法: 将密文转换为明文的转换算法。

解密密钥: 通过解密短发进行解密操作的密钥。

 

密码学分类

1. 按时间分

a. 古典密码:以字符为基本加密单元。

b. 现代密码:以信息块为基本加密单元。

 

2 按保密内容的算法划分

a. 受限制算法:算法的保密性基于保持算法的秘密。

b. 基于密钥算法:算法的保密性基于对密钥的保密。

 

3. 按密钥体制划分

a. 对称密码体制:也叫单钥或私钥密码体制,加密过程与解密过程使用同一套密钥。对应的算法就是对称加密算法,例如 DES , AES 

b. 非对称密码体制:也叫双钥或公钥密码体制,加密过程与解密过程使用不同的密钥。对应的算法就是非对称加密算法,例如 RSA 

 

4. 按明文处理方式划分

a. 流密码:也称为序列密码,加密时每次加密一位或者一个字节的明文。例如 RC4 算法。

b. 分组密码:加密时将明文分成固定长度的组,用同一个密钥和算法对每一组进行加密输出也是固定长度的明文。当最后一组大小不满足指定的分组大小时,

有两种处理模式:

 

无填充模式,直接对剩余数据进行加密,此组加密后大小与剩余数据有关;

有填充模式,对于不满足指定长度分组的进行数据填充;如果恰巧最后一组数据与指定分组大小相同,那么直接添加一个指定大小的分组;填充的最后一个字节记录了填充的字节数。

 

 

 

分组密码工作模式简介  

.电子密码本模–ECB

将明文的各个分组独立的使用相同的密钥进行加密,这种方式加密时各分组的加密独立进行互不干涉,因而可并行进行。同样因为各分组独立加密的缘故,相同的明文分组加密之后具有相同的密文。该模式容易暴露明文分组的统计规律和结构特征。不能防范替换攻击。 
其实照实现来看, ECB 的过程只是把明文进行分组,然后分别加密,最后串在一起的过程。当消息长度超过一个分组时,不建议使用该模式。在每个分组中增加随机位 ( 如 128 位分组中 96 位为有效明文, 32 位的随机数 ) 则可稍微提高其安全性 , 但这样无疑造成了加密过程中数据的扩张。

优点 :

1.简单;

2.有利于并行计算;

3.误差不会被传送;

缺点 :

1.不能隐藏明文的模式;

2.可能对明文进行主动攻击;

 

2.密码分组链接模 — CBC

需要一个初始化向量 IV ,第一组明文与初始化向量进行异或运算后再加密,以后的每组明文都与前一组的密文进行异或运算后再加密。 IV 不需要保密,它可以明文形式与密文一起传送。

优点:

1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

缺点:

1.不利于并行计算;

2.误差传递;

3.需要初始化向量IV

   

3. 密文反馈模式–CFB  

需要一个初始化向量IV ,加密后与第一个分组明文进行异或运算产生第一组密文,然后对第一组密文加密后再与第二组明文进行异或运算缠身第二组密文,一次类推,直到加密完毕。

优点:

1.隐藏了明文模式;

2.分组密码转化为流模式;

3.可以及时加密传送小于分组的数据;

缺点 :

1.不利于并行计算;

2.误差传送:一个明文单元损坏影响多个单元;

3.唯一的IV;

 

4. 输出反馈模式–OFB

需要一个初始化向量IV ,加密后得到第一次加密数据,此加密数据与第一个分组明文进行异或运算产生第一组密文,然后对第一次加密数据进行第二次加密,得到第二次加密数据,第二次加密数据再与第二组明文进行异或运算产生第二组密文,一次类推,直到加密完毕。

优点 :

1.隐藏了明文模式;

2.分组密码转化为流模式;

3.可以及时加密传送小于分组的数据;

缺点 :

1.不利于并行计算;

2. 对明文的主动攻击是可能的 ;

3. 误差传送:一个明文单元损坏影响多个单元 ;

 

 

 

5. 计数器模式–CTR

使用计数器,计数器初始值加密后与第一组明文进行异或运算产生第一组密文,

计数器增加,然后,加密后与下一组明文进行异或运算产生下一组密文,以此类推,直到加密完毕

优点 :

1. 可并行计算 ;

2. 安全性至少与CBC 模式一样好 ;

3. 加密与解仅涉及密码算法的加密 ;

缺点 :

1. 没有错误传播,不易确保数据完整性 ;

  

分组密码填充方式简介

PKCS5 : 填充字符串由一个值为 5 的字节序列组成,每个字节填充该字节序列的长度。 明确定义 Block 的大小是 8 位

PKCS7 : 填充字符串由一个值为 7 的字节序列组成,每个字节填充该字节序列的长度。 对于块的大小是不确定的,可以在 1-255 之间

ISO10126: 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。  

转自:http://aub.iteye.com/blog/1129339