加密算法详解AES/HmacSHA1/DES
Posted Alex_z0897
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加密算法详解AES/HmacSHA1/DES相关的知识,希望对你有一定的参考价值。
byte[] raw = sKey.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
这段代码使用的是AES加密算法,具体的实现方式是AES/ECB/PKCS5Padding。其中,AES是一种对称加密算法,ECB是一种工作模式,PKCS5Padding是一种填充方式。
AES算法:是一种常用的对称加密算法,其安全性高、加解密速度快,广泛应用于数据加密的领域。
ECB模式:是一种对称加密的工作模式,它将加密的数据按照块的方式进行处理,并使用相同的密钥进行加密,每一块数据都采用相同的算法进行处理。
PKCS5Padding:是一种填充方式,它可以将明文数据进行填充,使其满足块长度的要求。在这种填充方式中,如果原始数据的长度不足一块,会在末尾填充相应的字节数。如果原始数据长度等于一块,那么就会增加一个新块,新块中的所有字节都是填充数据。
因此,这段代码使用AES算法对sSrc进行加密,sKey是加解密所使用的密钥,raw是通过sKey获取的。使用Cipher类初始化加密模式后,调用doFinal()方法实现加密过程,获得加密后的结果。
SecretKeySpec signinKey = new SecretKeySpec(secret.getBytes(), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signinKey);
byte[] rawHmac;
rawHmac = mac.doFinal(content.getBytes(StandardCharsets.UTF_8));
这段代码使用的是HmacSHA1算法,是一种基于散列函数实现的消息认证码(MAC)。具体实现过程如下:
使用SecretKeySpec类创建HmacSHA1算法所需的秘钥,secret是加解密所使用的密钥。
SecretKeySpec signinKey = new SecretKeySpec(secret.getBytes(), “HmacSHA1”);
使用Mac类初始化MAC对象,用于数据的加密或验证操作。在这里,传入HmacSHA1算法。
Mac mac = Mac.getInstance(“HmacSHA1”);
通过init()方法对MAC对象进行初始化,将所需的秘钥传入进行初始化。
mac.init(signinKey);
将待签名的数据使用getBytes()方法获取字节数组,通过doFinal()方法对数据进行签名,返回签名后的结果。
byte[] rawHmac;
rawHmac = mac.doFinal(content.getBytes(StandardCharsets.UTF_8));
完成签名操作后,即可根据需要进行验签或者其他操作。
因此,这段代码完成了使用HmacSHA1算法对指定的密钥和数据进行签名(MAC)的过程。
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
byte[] dataBytes = data.getBytes();
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "DES");
IvParameterSpec ivspec = new IvParameterSpec(key.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(dataBytes);
这是DES算法在CBC分组模式下的加密实现,并采用PKCS5填充方式进行数据填充。具体步骤如下:
使用Cipher类创建DES加密对象,并指定CBC分组模式和PKCS5Padding填充方式。
Cipher cipher = Cipher.getInstance(“DES/CBC/PKCS5Padding”);
将待加密的字符串转换为字节数组。
byte[] dataBytes = data.getBytes();
指定密钥,创建SecretKeySpec对象,使用Des算法。
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), “DES”);
指定初始化向量,创建IvParameterSpec对象,并传入与密钥相同的值。
IvParameterSpec ivspec = new IvParameterSpec(key.getBytes());
Java Web学习数据加密方式详解
本文借鉴:chengbinbbs,FKNIGHT0X,Central-Perk(特此感谢!)
对称加密
定义:加密和解密使用相同密钥的算法。
常见的有DES、3DES、AES、PBE等加密算法,这几种算法安全性依次是逐渐增强的。
DES加密
特点:简便、密钥长度比较短。
/** * DES加密介绍 * DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究, * 后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力, * 24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现 * 。 * 注意:DES加密和解密过程中,密钥长度都必须是8的倍数 */ public class DESUtil /** * 加密 * * @param datasource byte[] 需要加密的数据.getBytes() * @param password String 密码(作用:生成密钥,长度要是8的倍数) * @return byte[] */ public static byte[] encrypt(byte[] datasource, String password) try SecureRandom random = new SecureRandom(); // 使用密码,创建一个DESKeySpec对象 DESKeySpec desKey = new DESKeySpec(password.getBytes()); //创建一个密匙工厂,然后用它把DESKeySpec转换成对应的密钥 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); //根据密钥工厂的入参生成对应的des密钥 SecretKey securekey = keyFactory.generateSecret(desKey); //Cipher对象实际完成加密操作 Cipher cipher = Cipher.getInstance("DES"); //用密匙初始化Cipher对象 cipher.init(Cipher.ENCRYPT_MODE, securekey, random); //现在,获取数据并加密 //正式执行加密操作 return cipher.doFinal(datasource); catch (Throwable e) e.printStackTrace(); return null; /** * 解密 * * @param src byte[] 密钥加密过后的信息 * @param password String * @return byte[] * @throws Exception */ public static byte[] decrypt(byte[] src, String password) throws Exception // DES算法要求有一个可信任的随机数源 SecureRandom random = new SecureRandom(); // 创建一个DESKeySpec对象 DESKeySpec desKey = new DESKeySpec(password.getBytes()); // 创建一个密匙工厂 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); // 将DESKeySpec对象转换成SecretKey对象 SecretKey securekey = keyFactory.generateSecret(desKey); // Cipher对象实际完成解密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher对象 cipher.init(Cipher.DECRYPT_MODE, securekey, random); // 真正开始解密操作 return cipher.doFinal(src); //测试 public static void main(String args[]) //待加密内容 String str = "测试内容"; //密码,长度要是8的倍数 String password = "9588028820109132570743325311898426347857298773549468758875018579537757772163084478873699447306034466200616411960574122434059469100235892702736860872901247123456"; byte[] result = DESUtil.encrypt(str.getBytes(), password); System.out.println("加密后:" + new String(result)); //直接将如上内容解密 try byte[] decryResult = DESUtil.decrypt(result, password); System.out.println("解密后:" + new String(decryResult)); catch (Exception e1) e1.printStackTrace();
AES加密
/** * AES 加密方法,是对称的密码算法(加密与解密的密钥一致),这里使用最大的 256 位的密钥 */ public class AESUtil /** * 获得一个 密钥长度为 256 位的 AES 密钥, * * @return 返回经 BASE64 处理之后的密钥字符串 */ public static String getStrKeyAES() throws NoSuchAlgorithmException, UnsupportedEncodingException //密钥生成器,指定生成AES类型的密钥 KeyGenerator keyGen = KeyGenerator.getInstance("AES"); //加密的强随机数 SecureRandom secureRandom = new SecureRandom(String.valueOf(System.currentTimeMillis()).getBytes("utf-8")); //初始化密钥生成器的长度为256位 keyGen.init(256, secureRandom); // 这里可以是 128、192、256、越大越安全 //生成密钥 SecretKey secretKey = keyGen.generateKey(); //Base64.getEncoder():使用base64编码来编码字节数据 return Base64.getEncoder().encodeToString(secretKey.getEncoded()); /** * 将使用 Base64 加密后的字符串类型的 SecretKey 解码为 SecretKey * * @param strKey * @return SecretKey */ public static SecretKey strKey2SecretKey(String strKey) byte[] bytes = Base64.getDecoder().decode(strKey); SecretKeySpec secretKey = new SecretKeySpec(bytes, "AES"); return secretKey; /** * 加密 * * @param content 待加密内容 * @param secretKey 加密使用的 AES 密钥 * @return 加密后的密文 byte[] */ public static byte[] encryptAES(byte[] content, SecretKey secretKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal(content); /** * 解密 * * @param content 待解密内容 * @param secretKey 解密使用的 AES 密钥 * @return 解密后的明文 byte[] */ public static byte[] decryptAES(byte[] content, SecretKey secretKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal(content);
非对称加密
定义:非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。一般公钥是公开的,私钥是自己保存。
常见的有RSA算法
RSA加密
/** * RSA公钥/私钥/签名工具包 * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman) * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式 * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密, * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全 * * @author IceWee * @version 1.0 * @date 2012-4-26 */ public class RSAUtils /** */ /** * 加密算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** * 签名算法 */ public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** * 获取公钥的key */ private static final String PUBLIC_KEY = "RSAPublicKey"; /** * 获取私钥的key */ private static final String PRIVATE_KEY = "RSAPrivateKey"; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * 生成密钥对(公钥和私钥) * * @return * @throws Exception */ public static Map<String, Object> genKeyPair() throws Exception //实例化一个密钥对生成器,并设置长度 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); //生成密钥对 KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); //公钥、私钥 Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; /** * 用私钥对信息生成数字签名 * * @param data 已加密数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception //解码私钥 byte[] keyBytes = Base64.decode(privateKey).getBytes(); //以编码格式来表示私钥 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); //根据RSA算法创建key工厂,并使用PKCS8编码生成一个私钥 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); //签名算法 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return new String(Base64.encode(signature.sign())); /** * 校验数字签名 * * @param data 已加密数据 * @param publicKey 公钥(BASE64编码) * @param sign 数字签名 * @return * @throws Exception */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception //解码公钥 byte[] keyBytes = Base64.decode(publicKey).getBytes(); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64.decode(sign).getBytes()); /** * 私钥解密 * * @param encryptedData 已加密数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception byte[] keyBytes = Base64.decode(privateKey).getBytes(); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) if (inputLen - offSet > MAX_DECRYPT_BLOCK) cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); else cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; /** * 公钥解密 * * @param encryptedData 已加密数据 * @param publicKey 公钥(BASE64编码) * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception byte[] keyBytes = Base64.decode(publicKey).getBytes(); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) if (inputLen - offSet > MAX_DECRYPT_BLOCK) cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); else cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; /** * 公钥加密 * * @param data 源数据 * @param publicKey 公钥(BASE64编码) * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception byte[] keyBytes = Base64.decode(publicKey).getBytes(); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) if (inputLen - offSet > MAX_ENCRYPT_BLOCK) cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); else cache = cipher.doFinal(data, offSet, inputLen - offSet); out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; /** * 私钥加密 * * @param data 源数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception byte[] keyBytes = Base64.decode(privateKey).getBytes(); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) if (inputLen - offSet > MAX_ENCRYPT_BLOCK) cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); else cache = cipher.doFinal(data, offSet, inputLen - offSet); out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; /** * 获取私钥 * * @param keyMap 密钥对 * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception Key key = (Key) keyMap.get(PRIVATE_KEY); return new String(Base64.encode(key.getEncoded())); /** * 获取公钥 * * @param keyMap 密钥对 * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception Key key = (Key) keyMap.get(PUBLIC_KEY); return new String(Base64.encode(key.getEncoded()));
以上是关于加密算法详解AES/HmacSHA1/DES的主要内容,如果未能解决你的问题,请参考以下文章