
本文共 12179 字,大约阅读时间需要 40 分钟。
在日常开发中的安全测试或安全功能研发时经常遇到加解密,涉及到对称加密和非对称加密。
在对称加密中常用DES(data encrption standard)算法和AES算法
DES:DES 加密算法是一种分组密码,以 64 位为分组对数据加密,它的密钥长度是 56 位,加密解密用同一算法。DES 加密算法是对密钥进行保密,而公开算法,包括加密和解密算法。这样,只有掌握了和发送方相同密钥的人才能解读由 DES 加密算法加密的密文数据。因此,破译 DES 加密算法实际上就是搜索密钥的编码。对于 56 位长度的密钥来说,如果用穷举法来进行搜索的话,其运算次数为 2 的 56 次方。
public class DES { private final static String DES = "DES"; public static void main(String[] args) throws Exception { String data = "DES对称加密算法"; String key = "asdfghjkl123456789"; //秘钥设置的长度必须大于等于 8 System.err.println(encrypt(data, key)); System.err.println(decrypt(encrypt(data, key), key)); } /** * Description 根据键值进行加密 */ public static String encrypt(String data, String key) throws Exception { byte[] bt = encrypt(data.getBytes(), key.getBytes()); String strs = new BASE64Encoder().encode(bt); return strs; } /** * Description 根据键值进行解密 */ public static String decrypt(String data, String key) throws IOException, Exception { if (data == null) { return null; } BASE64Decoder decoder = new BASE64Decoder(); byte[] buf = decoder.decodeBuffer(data); byte[] bt = decrypt(buf,key.getBytes()); return new String(bt); } /** * Description 根据键值进行加密 */ private static byte[] encrypt(byte[] data, byte[] key) throws Exception { // 生成一个可信任的随机数源 SecureRandom sr = new SecureRandom(); // 从原始密钥数据创建DESKeySpec对象 DESKeySpec dks = new DESKeySpec(key); // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); SecretKey securekey = keyFactory.generateSecret(dks); // Cipher对象实际完成加密操作 Cipher cipher = Cipher.getInstance(DES); // 用密钥初始化Cipher对象 cipher.init(Cipher.ENCRYPT_MODE, securekey, sr); return cipher.doFinal(data); } /** * Description 根据键值进行解密 */ private static byte[] decrypt(byte[] data, byte[] key) throws Exception { // 生成一个可信任的随机数源 SecureRandom sr = new SecureRandom(); // 从原始密钥数据创建DESKeySpec对象 DESKeySpec dks = new DESKeySpec(key); // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); SecretKey securekey = keyFactory.generateSecret(dks); // Cipher对象实际完成解密操作 Cipher cipher = Cipher.getInstance(DES); // 用密钥初始化Cipher对象 cipher.init(Cipher.DECRYPT_MODE, securekey, sr); return cipher.doFinal(data); }}//打印JozfxOVCs+RpROTmdXQtaE5mu97tjoNQDES对称加密算法
AES:AES 加密算法是密码学中的高级加密标准,该加密算法采用对称分组密码体制,密钥长度的最少支持为 128、192、256,分组长度 128 位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的区块加密标准,AES 标准用来替代原先的 DES,已经被多方分析且广为全世界所使用。
public class AES { private final static String AES = "AES"; private final static String ALGORITHM = "AES/ECB/PKCS5Padding"; public static void main(String[] args) throws Exception { // 此处使用AES-128-ECB加密模式,key需要为16位。 String cKey = "1234567890123456"; // 需要加密的字串 String cSrc = "DES对称加密算法"; System.out.println("原文是:" + cSrc); // 加密 String enString = Encrypt(cSrc, cKey); System.out.println("加密后的字串是:" + enString); // 解密 String DeString = Decrypt(enString, cKey); System.out.println("解密后的字串是:" + DeString); } // 加密 public static String Encrypt(String sSrc, String sKey) throws Exception { if (sKey == null) { System.out.print("Key为空null"); return null; } // 判断Key是否为16位 if (sKey.length() != 16) { System.out.print("Key长度不是16位"); return null; } byte[] raw = sKey.getBytes("utf-8"); SecretKeySpec skeySpec = new SecretKeySpec(raw, AES); Cipher cipher = Cipher.getInstance(ALGORITHM);//"算法/模式/补码方式" cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。 } // 解密 public static String Decrypt(String sSrc, String sKey) throws Exception { try { // 判断Key是否正确 if (sKey == null) { System.out.print("Key为空null"); return null; } // 判断Key是否为16位 if (sKey.length() != 16) { System.out.print("Key长度不是16位"); return null; } byte[] raw = sKey.getBytes("utf-8"); SecretKeySpec skeySpec = new SecretKeySpec(raw, AES); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密 try { byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original,"utf-8"); return originalString; } catch (Exception e) { System.out.println(e.toString()); return null; } } catch (Exception ex) { System.out.println(ex.toString()); return null; } }}//打印原文是:DES对称加密算法加密后的字串是:dT8DU7s8uAWviSBWHA7F5I2aeUSqIXpF6I7CxbmTzY4=解密后的字串是:DES对称加密算法
在非对称加密中常用RSA算法
RSA:生成密钥,介绍3中方法
- 命令行:可以使用openssl进行生成公钥和私钥。
-- 生成公钥和私钥openssl genrsa -out key.pem 1024 -out 指定生成文件,此文件包含公钥和私钥两部分,所以即可以加密,也可以解密 1024 生成密钥的长度
- 使用网站:生成密钥的网站,百度一下
- 使用代码:可以指定生成密钥的长度,最低是 512。
public static KeyPair buildKeyPair() throws NoSuchAlgorithmException { final int keySize = 2048; KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM); keyPairGenerator.initialize(keySize); return keyPairGenerator.genKeyPair();}
public class RSA { private static final Base64.Decoder decoder = Base64.getDecoder(); private static final Base64.Encoder encoder = Base64.getEncoder(); public static void main(String[] args) throws Exception { KeyPair keyPair = buildKeyPair(); String message = "RSA非对称加密算法"; byte[] encryptData = encrypt(keyPair.getPublic(), message); System.out.println(String.format("加密后的数据:%s",base64Encode(encryptData))); System.out.println(String.format("解密后的数据:%s",new String(decrypt(keyPair.getPrivate(),encryptData),"utf-8"))); String context = "加签的字符串"; String sign = signWithRSA(context, keyPair.getPrivate()); System.out.println(String.format("生成的签名:%s",sign)); Boolean checkSignWithRSA = checkSignWithRSA(context, keyPair.getPublic(), sign); System.out.println(String.format("校验的结果:%s",checkSignWithRSA.toString())); } /** * 生成密钥对 */ public static KeyPair buildKeyPair() throws NoSuchAlgorithmException { final int keySize = 2048; KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(keySize); return keyPairGenerator.genKeyPair(); } /** * 加密 */ public static byte[] encrypt(PublicKey publicKey, String message) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(message.getBytes("utf-8")); } /** * 解密 */ public static byte[] decrypt(PrivateKey privateKey, byte [] encrypted) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encrypted); } /** * 使用RSA签名 */ private static String signWithRSA(String content, PrivateKey privateKey) throws Exception { Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(privateKey); signature.update(content.getBytes("utf-8")); byte[] signed = signature.sign(); return base64Encode(signed); } /** * 使用RSA验签 */ private static boolean checkSignWithRSA(String content, PublicKey publicKey,String sign) throws Exception { Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initVerify(publicKey); signature.update(content.getBytes("utf-8")); return signature.verify(base64Decode(sign)); } private static String base64Encode(byte[] signed) { //编码 String encodedText = encoder.encodeToString(signed); return encodedText; } private static byte[] base64Decode(String sign) throws UnsupportedEncodingException { //解码 byte[] decode = decoder.decode(sign); return decode; }}//打印加密后的数据:j56URGDJjS2Meo3P698aj3JqZKKpOJIOghTawsdi1+ASQb9FgsC2QDPF/w78aghIo0SEY6Q7H7p2Slys/wH1VW5zFfy5/IdK6CK44nvnHMs+NmodCJrSeimoZnuFC92WRqryWgSC2l25pGaHrEVcR5jR7V6Mk8677TyUpDjyHPIPwAHBUVn8mydxKR0BtgP2J5pvFZJip7T+5sPavGixKLHHgRC+B660OHwPOGUXfvaNDjN6l5crSQlfNMBep9dzKLh/22RQHUVf8HkKTwR38LQM+sNvR23RE8q+Q2W/+mEx5WZLkXBBlcRQ4Ww/UvkmmADIxuurblUBtkP0mENEzw==解密后的数据:RSA非对称加密算法生成的签名:WezHTvgJExCvAL1gJbEsfAOVntzFac9FDmtX3qa1BO33QwHWOKGbsdH2Drk2MIVWS1db7grqwifi4w60tzH0Q7SU1iCJ1TOcQR4EI3PbIsY9VkLD+nRRyJKyTRstN8S+saJDV5NIzA9wb7x170DsIaUphLslU1XQR1Y0c7HY4WklzMfQ25kLIc7ocJP29tzknEnkcElqQVwxiGNIZehWmmHJZ2JMcbdTtLZEMtW5FC3pEhrvUtrEwENWhc4g8Dvix9LrSVoxPmRslMeL8ldHj5Ec4UsXR4mZldBKpdc5PO8oo6HbIFP2eX14ACpPFCQQnAjtQZ+9TOP/KuDzXduClQ==校验的结果:true
加签和验签
公钥是用来解密信息的,确保让别人知道这条信息是真的由我发布的,是完整正确的。接收者由此可知这条信息确实来自于拥有私钥的某人,这被称作数字签名,公钥的形式就是数字证书。所以这种我们称之为加签和验签。举例,银行 A 发布了一个银行客户端的补丁供所有用户更新,那为了确保人家下载的是正确完整的客户端,银行A会为这个程序打上一个数字签名(就是用银行A的私钥对这个程序加密然后发布),你需要在你的电脑里装上银行 A 的数字证书(就是银行对外发布的公钥),然后下载好这个程序,数字证书会去解密这个程序的数字签名,解密成功,补丁得以使用。同时你能知道这个补丁确实是来自这个银行 A,是由他发布的,而不是其他人发布的。
摘要算法常用MD5算法
数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法或散列算法。
public class MD5 { public static void main(String[] args) { String message = "123456789"; try { String md5Str = getMD5Str(message); System.out.println(md5Str); } catch (Exception e) { e.printStackTrace(); } } public static String getMD5Str(String str) throws Exception { try { // 生成一个MD5加密计算摘要 MessageDigest md = MessageDigest.getInstance("MD5"); // 计算md5函数 md.update(str.getBytes()); // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符 // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 return new BigInteger(1, md.digest()).toString(16); } catch (Exception e) { throw new Exception("MD5加密出现错误,"+e.toString()); } }}// 打印25f9e794323b453885f5181f1b624d0b
或
public class MD5Util { private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; public static void main(String[] args) { String sign = "3ae14696f82a547cfce841651b67342a1"; String message = "摘要"; String signature = encode(message); System.out.println(signature); boolean flag = signature.equals(sign); Assert.isTrue(flag, "签名错误"); } public static String encode(String origin) { return encode(origin, "UTF-8"); } public static String encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)) { resultString = byteArrayToHexString(md.digest(resultString.getBytes())); } else { resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); } } catch (Exception exception) { } return resultString; } private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) { resultSb.append(byteToHexString(b[i])); } return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) { n += 256; } int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; }}// 打印3ae14696f82a547cfce841651b67342a
转载地址:https://blog.csdn.net/leijie0322/article/details/113845573 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关于作者
