当前位置:

首页 > 编程开发 > Java实现常用的三种加密算法是什么

Java实现常用的三种加密算法是什么

前言编程中常见的加密算法有以下几种,它们在不同场景中分别有应用。除信息摘要算法外,其它加密方式都会需要密钥。信息摘要算法对称加密算法非对称加密算法密钥密钥(key,又常称金钥)是指某个用来完成加密、解密、完整性验证等密码学应用的秘密信息。密钥分类加解密中的密钥:对称加密中共享相同的密钥,非对称加密中分公钥和私钥,公钥加密私钥解密。消息认证码和数字签名中的密钥:在消息认证码中,消息发送方和接收方使用共享密钥进行认证。在数字签名中,签名使用私钥,而验证使用公钥。会话密钥和主密钥:每次通信只使用一次的密钥称为会

本文目录

      前言

      编程中常见的加密算法有以下几种,它们在不同场景中分别有应用。除信息摘要算法外,其它加密方式都会需要密钥。

      • 信息摘要算法

      • 对称加密算法

      • 非对称加密算法

      密钥

      密钥(key,又常称金钥)是指某个用来完成加密、解密、完整性验证等密码学应用的秘密信息。

      密钥分类

      • 加解密中的密钥:对称加密中共享相同的密钥,非对称加密中分公钥和私钥,公钥加密私钥解密。

      • 消息认证码和数字签名中的密钥:在消息认证码中,消息发送方和接收方使用共享密钥进行认证。在数字签名中,签名使用私钥,而验证使用公钥。

      • 会话密钥和主密钥:每次通信只使用一次的密钥称为会话密钥(session key)。相对于会话密钥,重复使用的密钥称为主密钥(master key)。

      密钥和密码

      密码一般是由用户生成,具有可读性,可以记忆和存储,常用于软件管理,而密钥是供实现加密算法的软件使用,不需要具备可读性(不过在编程中为了方便阅读都进行Base64)。我们也可以通过密码来生成密钥。

      密钥管理

      • 生成密钥:可以用随机数生成密钥,也可以用口令生成密钥。

      • 配送密钥:可采用事先共享密钥、使用密钥分配中心、使用公钥密码、使用Diffie-Hellman密钥交换。

      • 更新密钥

      • 保存密钥

      • 作废密钥

      密钥生成

      jdk 中 jce (Java Cryptography Extension) 包含了加密相关的所有API。

      生成对称加密算法的密钥

      Java实现常用的三种加密算法是什么

      public static SecretKey generateKey(int keySize) {
              KeyGenerator keyGenerator;
              try {
                  keyGenerator = KeyGenerator.getInstance("AES");
                  keyGenerator.init(keySize);
                  return keyGenerator.generateKey();
              } catch (NoSuchAlgorithmException e) {
                  // ignore
                  return null;
              }
          }

      生成对称非对称加密算法的密钥

      /**
           * 生成非对称密钥对
           *
           * @param keySize 密钥大小
           * @param random  指定随机来源,默认使用 JCAUtil.getSecureRandom()
           * @return 非对称密钥对
           * @throws NoSuchAlgorithmException NoSuchAlgorithm
           */
          public static PPKeys genKeysRSA(int keySize, SecureRandom random) throws NoSuchAlgorithmException {
              KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
              if (null != random) {
                  generator.initialize(keySize, random);
              } else {
                  generator.initialize(keySize);
              }
              KeyPair pair = generator.generateKeyPair();
              PPKeys keys = new PPKeys();
              PublicKey publicKey = pair.getPublic();
              PrivateKey privateKey = pair.getPrivate();
              keys.setPublicKey(Base64.getEncoder().encodeToString(publicKey.getEncoded()));
            keys.setPrivateKey(Base64.getEncoder().encodeToString(privateKey.getEncoded()));
              return keys;
          }

      密钥协商(Diffie-Hellman)

      密钥协商是一种协议,两方或多方在通过该协议建立相同的共享密钥,然后通讯内容进行对称加密传输,而不需要交换密钥。

      大致过程:每一方生成一个公私钥对并将公钥分发给其它方,当都获得其他方的公钥副本后就可以离线计算共享密钥。

      Java中提供了 KeyAgreement 可以实现密钥协商。

      Java实现常用的三种加密算法是什么

      • Alice 和 Bob 分别用他们的私钥初始化自己的密钥协商对象 KeyAgreement ,调用init() 方法;

      • 然后将通信的每一方的公钥 传入执行 doPhase(Key key, boolean lastPhase) ;

      • 各方生成共享密钥 generateSecret()。

      public static void diffieHellman() throws Exception {
              AlgorithmParameterGenerator dhParams = AlgorithmParameterGenerator.getInstance("DH");
              dhParams.init(1024);
              KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
              keyGen.initialize(dhParams.generateParameters().getParameterSpec(DHParameterSpec.class), new SecureRandom());
      
              KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
              KeyPair alicePair = keyGen.generateKeyPair();
              KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
              KeyPair bobPair = keyGen.generateKeyPair();
      
              aliceKeyAgree.init(alicePair.getPrivate());
              bobKeyAgree.init(bobPair.getPrivate());
      
              aliceKeyAgree.doPhase(bobPair.getPublic(), true);
              bobKeyAgree.doPhase(alicePair.getPublic(), true);
      
             boolean agree = Base64.getEncoder().encodeToString(aliceKeyAgree.generateSecret()).equals(
                Base64.getEncoder().encodeToString(bobKeyAgree.generateSecret())
              );
              System.out.println(agree);
          }

      信息摘要算法

      信息摘要算法又叫加密散列算法,加密过程不需要密钥,常见的加密散列算法有MD系列和SHA系列。

      一个理想的加密散列函数应该具备以下特性:

      • 任何信息传入后,输出的总是长度固定;

      • 消息摘要看起来是“随机的”,这样根据原始信息就很难推测出值;

      • 好的散列函数碰撞概率应该极低,也就是不同信息传入后得到相同值的概率;

      MD系列

      MD5信息摘要算法(MD5 Message-Digest Algorithm),一种被广泛使用的加密散列函数,输出出一个128位(16字节)的散列值(hash value),MD5最初设计为加密散列函数,而目前发现它存在大量漏洞,所以不建议直接用作加密,不过在非加密场景下如:数据完整性校验,文件完整性校验它仍然有广泛的应用。

      public static String md5(String content) {
              try {
                  MessageDigest digest = MessageDigest.getInstance("MD5");
                  byte[] bytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
                  return Hex.encodeHexString(bytes);
              } catch (final NoSuchAlgorithmException e) {
                  throw new IllegalArgumentException(e);
              }
          }

      SHA系列

      安全散列算法(Secure Hash Algorithm,缩写为SHA)是一个加密散列函数家族,是FIPS(美国联邦信息处理标准)所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

      它们分别包含 SHA-0、SHA-1、SHA-2、SHA-3,其中 SHA-0、SHA-1 输出长度是160位,SHA-2 包含 SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256,我们平时常用 SHA-256 。

      public static String sha256(String content) {
              try {
                  MessageDigest digest = MessageDigest.getInstance("SHA-256);
                  byte[] bytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
                  return Hex.encodeHexString(bytes);
              } catch (final NoSuchAlgorithmException e) {
                  throw new IllegalArgumentException(e);
              }
          }

      对称加密算法

      对称加密算法,双方持有相同密钥进行加解密,常见的对称加密算法:DES 3DES AES128 AES192 AES256。理解对称加密需要先明白下面几个概念:

      • 分组密码模式:将明文切割进行加密,再将密文拼接到一起。比如AES中会将明文数据切割为大小16字节的数据块,最后一块不够16字节时,使用Padding模式进行补充。

      • 填充(Padding):它有三种模式PKCS5、PKCS7和NOPADDING,PKCS5用缺少的字节数来填充,比如缺少5个字节就填充5个数字5,PKCS7缺少的字节数用0来填充。如果数据刚好是16的整数倍,PKCS5和PKCS7会再补充一个16字节数据来区分填充和有效数据,NOPADDING模式不需要填充。

      • 初始化向量:初始向量IV的作用是使加密更加安全可靠,在分组密码模式下IV大小对应数据块长度。

      • 加密模式:四种加密模式分别是:ECB(电子密码本模式)、CBC(密码分组链接模式)、CFB、OFB。ECB模式是仅仅使用明文和密钥来加密数据,所以该模式下不需要Padding,安全性也较弱,CBC模式数据分块并且使用传入IV依次进行异或操作,安全性也相对较高,所以目前一般都选择CBC模式。

      • 加密密钥:不同加密算法密钥长度不同,比如:DES 默认长度56位,3DES默认长度168位,也支持128位,AES默认128位,也支持192位,256位。我们一般根据密码生成密钥,密码长度需要满足算法密钥长度。

      DES

      DES 是对称加密算法领域中的典型算法,因为密钥默认长度为56 bit,所以密码长度需要大于 8 byte,DESKeySpec 取前 8 byte 进行密钥制作。

      public static String encryptDES(byte[] content, String password) {
              try {
                  SecureRandom random = new SecureRandom();
                  DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
                  SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
                  SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
                  Cipher cipher = Cipher.getInstance("DES");
                  cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
                  return Base64.getEncoder().encodeToString(cipher.doFinal(content));
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
          }
      
          public static String decryptDES(String content, String password) throws Exception {
              SecureRandom random = new SecureRandom();
              DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
              SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
              SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
              Cipher cipher = Cipher.getInstance("DES");
              cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
              return new String(cipher.doFinal(Base64.getDecoder().decode(content)));
          }

      3DES

      3DES(即Triple DES)。是DES算法的加强,它使用3条56位的密钥对数据进行三次加密。它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES,3DES更为安全。密钥默认长度 168 bit, 密码需要大于24 byte,IV 是 8 byte 的随机数字和字母数组。

      public static String encrypt3DESECB(String content, String key, String iv) {
              try {
                  IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
                  DESedeKeySpec dks = new DESedeKeySpec(key.getBytes(StandardCharsets.UTF_8));
                  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
                  SecretKey secretkey = keyFactory.generateSecret(dks);
                  Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
                  cipher.init(Cipher.ENCRYPT_MODE, secretkey, ivSpec);
                  return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)));
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
          }
      
          public static String decrypt3DESECB(String content, String key, String iv) {
              try {
                  IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
                  DESedeKeySpec dks = new DESedeKeySpec(key.getBytes(StandardCharsets.UTF_8));
                  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
                  SecretKey secretkey = keyFactory.generateSecret(dks);
                  Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
                  cipher.init(Cipher.DECRYPT_MODE, secretkey, ivSpec);
                  return new String(cipher.doFinal(Base64.getDecoder().decode(content)), StandardCharsets.UTF_8);
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
          }

      AES

      AES 高级数据加密标准,能够有效抵御已知的针对DES算法的所有攻击,默认密钥长度为128 bit,还可以供选择 192 bit,256 bit。AES-128 AES-192 AES-256

      默认 AES-128 ,使用 PBEKeySpec 生成固定大小的密钥。

      public static String encryptAES128(String plainText, String password, String salt) throws Exception {
              SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
              byte[] saltBytes = salt.getBytes(StandardCharsets.UTF_8);
              // AES-128 密钥长度为128bit
              PBEKeySpec spec = new PBEKeySpec(
                password.toCharArray(),
                saltBytes,
                1000,
                128
              );
              SecretKey secretKey = factory.generateSecret(spec);
              SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
              Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
              AlgorithmParameters params = cipher.getParameters();
              IvParameterSpec iv = params.getParameterSpec(IvParameterSpec.class);
      
              cipher.init(Cipher.ENCRYPT_MODE, secret, iv);
              byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
      
              String encodedText = Base64.getEncoder().encodeToString(encryptedTextBytes);
              String encodedIV = Base64.getEncoder().encodeToString(iv.getIV());
              String encodedSalt = Base64.getEncoder().encodeToString(saltBytes);
              return encodedSalt + "." + encodedIV + "." + encodedText;
          }
      
      
          public static String decryptAES128(String encryptedText, String password) throws Exception {
              String[] fields = encryptedText.split("\\.");
              byte[] saltBytes = Base64.getDecoder().decode(fields[0]);
              byte[] ivBytes = Base64.getDecoder().decode(fields[1]);
              byte[] encryptedTextBytes = Base64.getDecoder().decode(fields[2]);
      
              SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
              PBEKeySpec spec = new PBEKeySpec(
                password.toCharArray(),
                saltBytes,
                1000,
                128
              );
      
              SecretKey secretKey = factory.generateSecret(spec);
              SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
              Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
              cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
              byte[] decryptedTextBytes;
              try {
                  decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
                  return new String(decryptedTextBytes);
              } catch (IllegalBlockSizeException | BadPaddingException e) {
                  throw new RuntimeException(e);
              }
          }

      使用 AES-256 时可能会出现下面异常:

      java.security.InvalidKeyException: Illegal key size

      JDK 1.8.0_161 及以上版本默认已经启用无限强度加密:

      static {
              java.security.Security.setProperty("crypto.policy", "unlimited");
          }

      JDK 1.8.0_161以前版本需要手动安装 jce 策略文件(下载地址)

      非对称加密算法

      非对称加密使用一对密钥,公钥用作加密,私钥则用作解密。关于密钥大小,截至2020年,公开已知的最大RSA密钥是破解的是829位的RSA-250,建议至少使用 2048 位密钥。

      Java实现常用的三种加密算法是什么

      public static String encrypt(byte[] publicKey, String plainText) {
              X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
              KeyFactory kf;
              try {
                  kf = KeyFactory.getInstance("RSA");
                  PublicKey publicKeySecret = kf.generatePublic(keySpec);
                  Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                  cipher.init(Cipher.ENCRYPT_MODE, publicKeySecret);
                  byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
                  return new String(Base64.getEncoder().encode(encryptedBytes));
              } catch (Exception e) {
                  log.error("Rsa encrypt error ", e);
                  throw new RuntimeException(e);
              }
          }
      
          public static String decrypt(byte[] privateKey, String encryptedText) {
              PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
              KeyFactory kf;
              try {
                  kf = KeyFactory.getInstance("RSA");
                  PrivateKey privateKeySecret = kf.generatePrivate(keySpec);
                  Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                  cipher.init(Cipher.DECRYPT_MODE, privateKeySecret);
                  return new String(cipher.doFinal(Base64.getDecoder().decode(encryptedText)), StandardCharsets.UTF_8);
              } catch (Exception e) {
                  log.error("Rsa decrypt error ", e);
                  throw new RuntimeException(e);
              }
          }
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Java
      相关文章 更多
      Java单元测试入门:使用JUnit 5编写第一个测试用例
      Java单元测试入门:使用JUnit 5编写第一个测试用例

      面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

      Java变量未初始化报错解析:局部变量与成员变量默认值差异
      Java变量未初始化报错解析:局部变量与成员变量默认值差异

      深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

      详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

      Java中final与static final常量的定义及初始化规则
      Java中final与static final常量的定义及初始化规则

      深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

      Java抽象方法与接口方法的区别及选型建议
      Java抽象方法与接口方法的区别及选型建议

      深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

      Java实现HTTP请求与JSON解析的完整代码示例
      Java实现HTTP请求与JSON解析的完整代码示例

      本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

      Java递归出现StackOverflowError的原因分析及栈空间优化方案
      Java递归出现StackOverflowError的原因分析及栈空间优化方案

      详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

      Java空指针异常(NPE)的代码排查与修复实例
      Java空指针异常(NPE)的代码排查与修复实例

      针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

      selenium上传文件教程本地文件路径设置方法
      selenium上传文件教程本地文件路径设置方法

      深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

      针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。