1 概念

JCA: Java密码体系结构 Java Cryptography Architecture
JCE(Java Cryptography Extension),在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。现在JCE已经捆绑在JDK中,所以,这里JCE是JCA的一部分

JCA包含一个提供者【Provider】体系结构和一组用于数字签名,消息摘要(哈希),证书和证书验证,加密(对称/非对称块/流密码),密钥生成管理和安全随机数生成等等的API。
这些API允许开发人员将安全性轻松集成到应用程序代码中。

JCA包含两个软件组件:

  • 定义和支持Provider为其提供实现的加密服务的框架。 这个框架包含了诸如java.security,javax.crypto,javax.crypto.spec和javax.crypto.interfaces等软件包。
  • Sun,SunRsaSign,SunJCE等实际提供者都包含了具体的加密实现。

2 架构

2.1 加密服务提供者(CSP)

java.security.Provider是所有安全提供程序的基类。 每个CSP都包含这个类的一个实例,它包含了提供者的名字,并列出了它实现的所有安全服务/算法。 当需要特定算法的实例时,JCA框架会咨询提供者的数据库,如果找到合适的匹配项,则创建该实例。

Provider包含一个包(或一组包),为声明的加密算法提供具体的实现。 每个JDK安装都默认安装并配置了一个或多个提供程序。 其他提供者可以静态或动态添加(参见Provider和Security类)。 客户端可以配置其运行时环境来指定提供程序的首选顺序。 首选顺序是在没有请求特定提供者时提供者搜索请求的服务的顺序。

要使用JCA,应用程序只需要请求特定类型的对象(如MessageDigest)和特定的算法或服务(如“SHA-256”算法),并从一个已安装的提供者获取实现。 或者,程序可以请求来自特定提供者的对象。 每个提供者都有一个名字来引用它。

应用程序需要一个“AES”算法的javax.crypto.Cipher实例,并不关心使用哪个提供者。应用程序调用Cipher引擎类的getInstance()工厂方法,然后请求JCA框架查找支持“AES”的第一个提供程序实例。该框架会咨询每个已安装的提供者,并获取提供者类的提供者实例
在这里插入图片描述
在调用时,不指定提供者 和 指定提供者的调用流程:
在这里插入图片描述

2.2 provider 提供者

provider提供者,这里的全称是 Cryptographic Service Provider (CSP),是指实现一个或多个密码服务(如数字签名算法,消息摘要算法和密钥转换服务)的包或一组包。 每个JDK安装都默认安装并配置了一个或多个provider包。用户可以静态或动态添加其他provider。
JDK中的加密库出于历史原因,由几个不同的提供者实现:

  • SUN
  • SunRsaSign
  • SunEC
  • SunJSSE
  • SunJCE
  • SunJGSS
  • SunSASL
  • XMLDSig
  • SunPCSC
  • SunMSCAPI

java.security.Provider是所有安全提供程序的基类

获取提供者和算法的代码示例:

		System.out.println("|提供者|算法|");
        System.out.println("|:---|:---|");
        for(Provider provider: Security.getProviders()){
            for(Provider.Service service:provider.getServices()){
                System.out.println("|"+provider.getName()+"|"+service.getAlgorithm()+"|");
            }
        }

Engine类和算法

引擎类为特定类型的密码服务提供接口,而不依赖于特定的密码算法或提供者。 引擎需要提供如下功能:

  • 密码操作(加密,数字签名,消息摘要等),
  • 发生器或密码材料的转换器(密钥和算法参数)
  • 对象(密钥库或证书)封装了密码数据,可以在更高的抽象层使用。
引擎类功能
SecureRandom用于生成随机或伪随机数字。
MessageDigest用于计算指定数据的消息摘要(散列)。
Signature使用密钥初始化,这些签名用于签署数据并验证数字签
Cipher用密钥初始化,用于加密/解密数据。存在各种类型的算法
Message Authentication Codes(MAC)与MessageDigests一样,它们也会生成散列值,但是首先使用密钥初始化以保护消息的完整性。
KeyFactory用于将Key类型的现有不透明密钥转换为密钥规范(底层密钥材料的透明表示),反之亦然。
SecretKeyFactory用于将SecretKey类型的现有不透明加密密钥转换为密钥规范(底层密钥材料的透明表示),反之亦然。 SecretKeyFactorys是专门的KeyFactorys,只能创建密钥(对称)。
KeyPairGenerator用于生成一对适用于指定算法的公钥和私钥。
KeyGenerator用于生成与指定算法一起使用的新密钥。
KeyAgreement由两方或多方使用,商定和建立一个特定的密钥,用于特定的密码操作。
AlgorithmParameters用于存储特定算法的参数,包括参数编码和解码。
AlgorithmParameterGenerator用于生成适合于指定算法的一组AlgorithmParameters。
KeyStore用于创建和管理密钥库。密钥库是密钥的数据库。密钥库中的私钥具有与其关联的证书链,用于验证相应的公钥。密钥库还包含来自可信实体的证书。
CertificateFactory用于创建公钥证书和证书吊销列表(CRL)。
CertPathBuilder用于构建证书链(也称为证书路径)。
CertPathValidator用于验证证书链。
CertStore用于从存储库中检索证书和CRL。
注意生成器可以创建具有全新内容的对象,而工厂只能从现有材料(例如编码)中创建对象。

3 使用示例

3.1 MessageDigest使用示例

以md5加密,演示MessageDigest的使用

public static void main(String[] args) {
        byte[] content = "hello world".getBytes();
        System.out.println(DigestUtils.md5DigestAsHex(content));
        System.out.println(DigestUtils.digestAsHexString("MD5", content));

        for (String algName : Security.getAlgorithms("MessageDigest")) {
            System.out.println(algName + "==>" + DigestUtils.digestAsHexString(algName, content));
        }
    }

3.2 MessageDigest工具类

public class DigestUtils {

    private static final String MD5_ALGORITHM_NAME = "MD5";

    private static final char[] HEX_CHARS =
            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};


    /**
     * Calculate the MD5 digest of the given bytes.
     *
     * @param bytes the bytes to calculate the digest over
     * @return the digest
     */
    public static byte[] md5Digest(byte[] bytes) {
        return digest(MD5_ALGORITHM_NAME, bytes);
    }

    /**
     * Return a hexadecimal string representation of the MD5 digest of the given bytes.
     *
     * @param bytes the bytes to calculate the digest over
     * @return a hexadecimal digest string
     */
    public static String md5DigestAsHex(byte[] bytes) {
        return digestAsHexString(MD5_ALGORITHM_NAME, bytes);
    }

    /**
     * Append a hexadecimal string representation of the MD5 digest of the given
     * bytes to the given {@link StringBuilder}.
     *
     * @param bytes   the bytes to calculate the digest over
     * @param builder the string builder to append the digest to
     * @return the given string builder
     */
    public static StringBuilder appendMd5DigestAsHex(byte[] bytes, StringBuilder builder) {
        return appendDigestAsHex(MD5_ALGORITHM_NAME, bytes, builder);
    }

    public static String digestAsHexString(String algorithm, byte[] bytes) {
        char[] hexDigest = digestAsHexChars(algorithm, bytes);
        return new String(hexDigest);
    }

    public static StringBuilder appendDigestAsHex(String algorithm, byte[] bytes, StringBuilder builder) {
        char[] hexDigest = digestAsHexChars(algorithm, bytes);
        return builder.append(hexDigest);
    }


    /**
     * Create a new {@link MessageDigest} with the given algorithm.
     * Necessary because {@code MessageDigest} is not thread-safe.
     */
    private static MessageDigest getDigest(String algorithm) {
        try {
            return MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException ex) {
            throw new IllegalStateException("Could not find MessageDigest with algorithm \"" + algorithm + "\"", ex);
        }
    }

    private static byte[] digest(String algorithm, byte[] bytes) {
        return getDigest(algorithm).digest(bytes);
    }

    private static char[] digestAsHexChars(String algorithm, byte[] bytes) {
        byte[] digest = digest(algorithm, bytes);
        return encodeHex(digest);
    }

    private static char[] encodeHex(byte[] bytes) {
        char[] chars = new char[32];
        for (int i = 0; i < chars.length; i = i + 2) {
            byte b = bytes[i / 2];
            chars[i] = HEX_CHARS[(b >>> 0x4) & 0xf];
            chars[i + 1] = HEX_CHARS[b & 0xf];
        }
        return chars;
    }

}

参考

【Java加密】JCA体系结构
Java –可用的MessageDigest算法列表
Java生成MD5的两种方式

provider及算法

提供者算法
SUNSHA1PRNG
SUNSHA1withDSA
SUNNONEwithDSA
SUNSHA224withDSA
SUNSHA256withDSA
SUNDSA
SUNMD2
SUNMD5
SUNSHA
SUNSHA-224
SUNSHA-256
SUNSHA-384
SUNSHA-512
SUNDSA
SUNDSA
SUNDSA
SUNX.509
SUNJKS
SUNCaseExactJKS
SUNDKS
SUNJavaPolicy
SUNJavaLoginConfig
SUNPKIX
SUNPKIX
SUNLDAP
SUNCollection
SUNcom.sun.security.IndexedCollection
SunRsaSignRSA
SunRsaSignRSA
SunRsaSignMD2withRSA
SunRsaSignMD5withRSA
SunRsaSignSHA1withRSA
SunRsaSignSHA224withRSA
SunRsaSignSHA256withRSA
SunRsaSignSHA384withRSA
SunRsaSignSHA512withRSA
SunECEC
SunECEC
SunECNONEwithECDSA
SunECSHA1withECDSA
SunECSHA224withECDSA
SunECSHA256withECDSA
SunECSHA384withECDSA
SunECSHA512withECDSA
SunECEC
SunECECDH
SunJSSERSA
SunJSSERSA
SunJSSEMD2withRSA
SunJSSEMD5withRSA
SunJSSESHA1withRSA
SunJSSEMD5andSHA1withRSA
SunJSSESunX509
SunJSSENewSunX509
SunJSSESunX509
SunJSSEPKIX
SunJSSETLSv1
SunJSSETLSv1.1
SunJSSETLSv1.2
SunJSSETLS
SunJSSEDefault
SunJSSEPKCS12
SunJCERSA
SunJCEDES
SunJCEDESede
SunJCEDESedeWrap
SunJCEPBEWithMD5AndDES
SunJCEPBEWithMD5AndTripleDES
SunJCEPBEWithSHA1AndDESede
SunJCEPBEWithSHA1AndRC2_40
SunJCEPBEWithSHA1AndRC2_128
SunJCEPBEWithSHA1AndRC4_40
SunJCEPBEWithSHA1AndRC4_128
SunJCEPBEWithHmacSHA1AndAES_128
SunJCEPBEWithHmacSHA224AndAES_128
SunJCEPBEWithHmacSHA256AndAES_128
SunJCEPBEWithHmacSHA384AndAES_128
SunJCEPBEWithHmacSHA512AndAES_128
SunJCEPBEWithHmacSHA1AndAES_256
SunJCEPBEWithHmacSHA224AndAES_256
SunJCEPBEWithHmacSHA256AndAES_256
SunJCEPBEWithHmacSHA384AndAES_256
SunJCEPBEWithHmacSHA512AndAES_256
SunJCEBlowfish
SunJCEAES
SunJCEAES_128/ECB/NoPadding
SunJCEAES_128/CBC/NoPadding
SunJCEAES_128/OFB/NoPadding
SunJCEAES_128/CFB/NoPadding
SunJCEAES_128/GCM/NoPadding
SunJCEAES_192/ECB/NoPadding
SunJCEAES_192/CBC/NoPadding
SunJCEAES_192/OFB/NoPadding
SunJCEAES_192/CFB/NoPadding
SunJCEAES_192/GCM/NoPadding
SunJCEAES_256/ECB/NoPadding
SunJCEAES_256/CBC/NoPadding
SunJCEAES_256/OFB/NoPadding
SunJCEAES_256/CFB/NoPadding
SunJCEAES_256/GCM/NoPadding
SunJCEAESWrap
SunJCEAESWrap_128
SunJCEAESWrap_192
SunJCEAESWrap_256
SunJCERC2
SunJCEARCFOUR
SunJCEDES
SunJCEDESede
SunJCEBlowfish
SunJCEAES
SunJCERC2
SunJCEARCFOUR
SunJCEHmacMD5
SunJCEHmacSHA1
SunJCEHmacSHA224
SunJCEHmacSHA256
SunJCEHmacSHA384
SunJCEHmacSHA512
SunJCEDiffieHellman
SunJCEDiffieHellman
SunJCEDiffieHellman
SunJCEDiffieHellman
SunJCEDES
SunJCEDESede
SunJCEPBE
SunJCEPBEWithMD5AndDES
SunJCEPBEWithMD5AndTripleDES
SunJCEPBEWithSHA1AndDESede
SunJCEPBEWithSHA1AndRC2_40
SunJCEPBEWithSHA1AndRC2_128
SunJCEPBEWithSHA1AndRC4_40
SunJCEPBEWithSHA1AndRC4_128
SunJCEPBES2
SunJCEPBEWithHmacSHA1AndAES_128
SunJCEPBEWithHmacSHA224AndAES_128
SunJCEPBEWithHmacSHA256AndAES_128
SunJCEPBEWithHmacSHA384AndAES_128
SunJCEPBEWithHmacSHA512AndAES_128
SunJCEPBEWithHmacSHA1AndAES_256
SunJCEPBEWithHmacSHA224AndAES_256
SunJCEPBEWithHmacSHA256AndAES_256
SunJCEPBEWithHmacSHA384AndAES_256
SunJCEPBEWithHmacSHA512AndAES_256
SunJCEBlowfish
SunJCEAES
SunJCEGCM
SunJCERC2
SunJCEOAEP
SunJCEDiffieHellman
SunJCEDES
SunJCEDESede
SunJCEPBEWithMD5AndDES
SunJCEPBEWithMD5AndTripleDES
SunJCEPBEWithSHA1AndDESede
SunJCEPBEWithSHA1AndRC2_40
SunJCEPBEWithSHA1AndRC2_128
SunJCEPBEWithSHA1AndRC4_40
SunJCEPBEWithSHA1AndRC4_128
SunJCEPBEWithHmacSHA1AndAES_128
SunJCEPBEWithHmacSHA224AndAES_128
SunJCEPBEWithHmacSHA256AndAES_128
SunJCEPBEWithHmacSHA384AndAES_128
SunJCEPBEWithHmacSHA512AndAES_128
SunJCEPBEWithHmacSHA1AndAES_256
SunJCEPBEWithHmacSHA224AndAES_256
SunJCEPBEWithHmacSHA256AndAES_256
SunJCEPBEWithHmacSHA384AndAES_256
SunJCEPBEWithHmacSHA512AndAES_256
SunJCEPBKDF2WithHmacSHA1
SunJCEPBKDF2WithHmacSHA224
SunJCEPBKDF2WithHmacSHA256
SunJCEPBKDF2WithHmacSHA384
SunJCEPBKDF2WithHmacSHA512
SunJCEHmacMD5
SunJCEHmacSHA1
SunJCEHmacSHA224
SunJCEHmacSHA256
SunJCEHmacSHA384
SunJCEHmacSHA512
SunJCEHmacPBESHA1
SunJCEPBEWithHmacSHA1
SunJCEPBEWithHmacSHA224
SunJCEPBEWithHmacSHA256
SunJCEPBEWithHmacSHA384
SunJCEPBEWithHmacSHA512
SunJCESslMacMD5
SunJCESslMacSHA1
SunJCEJCEKS
SunJCESunTlsPrf
SunJCESunTls12Prf
SunJCESunTlsMasterSecret
SunJCESunTlsKeyMaterial
SunJCESunTlsRsaPremasterSecret
SunJGSS1.2.840.113554.1.2.2
SunJGSS1.3.6.1.5.5.2
SunSASLDIGEST-MD5
SunSASLNTLM
SunSASLGSSAPI
SunSASLEXTERNAL
SunSASLPLAIN
SunSASLCRAM-MD5
SunSASLCRAM-MD5
SunSASLGSSAPI
SunSASLDIGEST-MD5
SunSASLNTLM
XMLDSighttp://www.w3.org/2006/12/xml-c14n11#WithComments
XMLDSighttp://www.w3.org/2000/09/xmldsig#base64
XMLDSighttp://www.w3.org/TR/1999/REC-xslt-19991116
XMLDSighttp://www.w3.org/2001/10/xml-exc-c14n#
XMLDSighttp://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments
XMLDSighttp://www.w3.org/2000/09/xmldsig#enveloped-signature
XMLDSighttp://www.w3.org/2002/06/xmldsig-filter2
XMLDSigDOM
XMLDSighttp://www.w3.org/TR/2001/REC-xml-c14n-20010315
XMLDSighttp://www.w3.org/2001/10/xml-exc-c14n#WithComments
XMLDSighttp://www.w3.org/2006/12/xml-c14n11
XMLDSighttp://www.w3.org/TR/1999/REC-xpath-19991116
XMLDSigDOM
SunPCSCPC/SC
SunMSCAPIWindows-PRNG
SunMSCAPIWindows-MY
SunMSCAPIWindows-ROOT
SunMSCAPINONEwithRSA
SunMSCAPISHA1withRSA
SunMSCAPISHA256withRSA
SunMSCAPISHA384withRSA
SunMSCAPISHA512withRSA
SunMSCAPIMD5withRSA
SunMSCAPIMD2withRSA
SunMSCAPIRSA
SunMSCAPIRSA
SunMSCAPIRSA/ECB/PKCS1Padding
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐