加密服务总是关联到一个特定的算法或类型,它既提供了密码操作(如Digital Signature或MessageDigest),生成或供应所需的加密材料(Key或Parameters)加密操作,也会以一个安全的方式生成数据对象(KeyStore或Certificate),封装(压缩)密钥(可以用于加密操作)。

Java Security API中,一个engine class就是定义了一种加密服务,不同的engine class提供不同的服务。下面就来看看有哪些engine class:

1)MessageDigest:对消息进行hash算法生成消息摘要(digest)。

2)Signature:对数据进行签名、验证数字签名。

3)KeyPairGenerator:根据指定的算法生成配对的公钥、私钥。

4)KeyFactory:根据Key说明(KeySpec)生成公钥或者私钥。

5)CertificateFactory:创建公钥证书和证书吊销列表(CRLs)。

6)KeyStore:keystore是一个keys的数据库。Keystore中的私钥会有一个相关联的证书链,证书用于鉴定对应的公钥。一个keystore也包含其它的信任的实体。

7)AlgorithmParameters:管理算法参数。KeyPairGenerator就是使用算法参数,进行算法相关的运算,生成KeyPair的。生成Signature时也会用到。

8)AlgorithmParametersGenerator:用于生成AlgorithmParameters。

9)SecureRandom:用于生成随机数或者伪随机数。

10)CertPathBuilder:用于构建证书链。

11)CertPathValidator:用于校验证书链。

12)CertStore:存储、获取证书链、CRLs到(从)CertStore中。

从上面这些engine class中,可以看出JCA(Java加密框架)中主要就是提供了4种服务:Digest、Key、Cert、Signature、Alogorithm。

1) 对消息内容使用某种hash算法就可以生成Digest。

2) 利用KeyFactory、KeyPairGenerator就可以生成公钥、私钥。

3) 证书中心使用公钥就可生成Cert。

4) 可以使用私钥和Digest就可以消息进行签名Signature。

5) 不论是Digest、Key、Cert、Signature,都要使用到算法Algorithm。

JCA Core API

1)engine class的提供商Provider

从JCA的设计上来说,这些engine的实现都离不开Provider。

这个类继承了Properties,提供了JCA中的engine class。每个engine class都有getInstance()方法,它们都是从provider中获取相关实例的。所以说Provider是JCA engine class的提供商。

2)管理Provider的工具:Security

其实就是一个存放Provider的集合。如果你自定义了一个Provider,可以使用Java Security属性文件配置provider,也可以直接使用Security采用编程的方式来添加Provider。然后就可以使用自定义的engine class了。

Java Security 属性文件在Java Security Policy中已有提过。在安装目录下:

下面是一个自定义的Provider:

/*** @author fs1194361820@163.com*/
public class XYZProvider extends Provider{public XYZProvider(){super("XYZ", 1.0, "XYZ Security Provider v1.0");put("MessageDigest.XYZ", XYZMessageDigest.class.getName());}
}

已经默认配置了下列Provider:

配置为:security.provider.11=com.fjn.security.XYZProvider 即可。

编码方式就更加简单了:Security.addProvider(new XYZProvider());

3)消息摘要服务:MessageDigest

消息摘要服务其实就是使用hash算法将一段消息(可以是字符串、文件内容、html等)进行计算生成的一个byte[]。

常用加密算法MD5、SHA、SHA-1其实都是hash算法。

下面就给一个简单的MD5算法工具:

package com.fjn.util;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/*** * @author fs1194361820@163.com**/
public class MD5 {private static MessageDigest md5MsgDigest;static{try {md5MsgDigest=MessageDigest.getInstance("md5");} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}// 转字符串public static String byte2hex(byte[] b){ String hs = "";String stmp = "";for (int n = 0; n < b.length; n++) {stmp = Integer.toHexString(b[n] & 0xFF);if (stmp.length() == 1)hs = hs + "0" + stmp;elsehs = hs + stmp;}return hs.toUpperCase();}public static String getMD5(String srcMsg){if(srcMsg == null){throw new IllegalArgumentException("srcMsg is null.");}byte[] md5Bytes=md5MsgDigest.digest(srcMsg.getBytes());return byte2hex(md5Bytes);}public static void main(String[] args) {System.out.println(MD5.getMD5("hello"));System.out.println(MD5.getMD5("world"));}
}

View Code

Md5算法我并没有去实现,因为在JDK中已经内置了md5算法。上面的代码就是使用消息摘要服务,并使用md5算法,生成相应的摘要。

下面来一个自定义的MessageDigest:

package com.fjn.security.messageDigest;import java.security.MessageDigest;
/*** @author fs1194361820@163.com*/
public class XYZMessageDigest extends MessageDigest{private int hash;private int store;private int count;public XYZMessageDigest(){super("XYZ");engineReset();}/*** 算法执行过程,每次执行{@link MessageDigest#update(byte)}时,都会调用这个方法,* 也就是使用这个算法对在已经计算的数据的基础上再次计算,计算出最新的结果*/@Overrideprotected void engineUpdate(byte b) {switch (count) {case 0:store = (b << 24) & 0xff000000;break;case 1:store |= (b << 16) & 0x00ff0000;break;case 2:store |= (b << 8) & 0x0000ff00;break;case 3:store |= (b << 0) & 0x000000ff;break;}count++;if(count==4){hash = hash ^ store;count = 0;store = 0;}}@Overrideprotected void engineUpdate(byte[] b, int offset, int length) {for (int i = 0; i < length; i++){engineUpdate(b[i + offset]);}}/*** 每次执行{@link MessageDigest#digest()}时,都会获取之前计算好的结果。* 同时也会将数据置为初始状态。*/@Overrideprotected byte[] engineDigest() {while (count != 0){engineUpdate((byte) 0);}byte b[] = new byte[4];b[0] = (byte) (hash >>> 24);b[1] = (byte) (hash >>> 16);b[2] = (byte) (hash >>>  8);b[3] = (byte) (hash >>>  0);engineReset();return b;}/*** 数据转为初始状态*/@Overrideprotected void engineReset() {hash = 0;store = 0;count = 0;        }}

View Code

这个自定义的MessageDigest中备注的内容,其实就是MessageDigest的执行过程,所有的MessageDigest都要遵从这个过程的。

测试用例:

package com.fjn.security.messageDigest;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.MessageDigest;
import java.security.Security;public class XYZMessageDigestTest {private static String filename="MessageDigestTest.txt";static{Security.addProvider(new XYZProvider());}public static void main(String[] args) throws Exception {XYZMessageDigestTest test=new XYZMessageDigestTest();test.writeMessage();test.readMessage();}public void writeMessage() throws Exception {File file=new File(filename);file.deleteOnExit();file.createNewFile();FileOutputStream fos = new FileOutputStream(file);MessageDigest md = MessageDigest.getInstance("XYZ");ObjectOutputStream oos = new ObjectOutputStream(fos);String data = "This have I thought good to deliver thee, "+"that thou mightst not lose the dues of rejoicing " +"by being ignorant of what greatness is promised thee.";byte buf[] = data.getBytes();md.update(buf);oos.writeObject(data);  // original messageoos.writeObject(md.digest()); // digest
        oos.close();}public void readMessage() throws Exception{File file=new File(filename);FileInputStream fis=new FileInputStream(file);ObjectInputStream ois=new ObjectInputStream(fis);Object o = ois.readObject(); // String data: original messageif (!(o instanceof String)) {System.out.println("Unexpected data in file");System.exit(-1);}String data = (String) o;System.out.println("Got message : " + data);o = ois.readObject();   // byte[] : digestif (!(o instanceof byte[])) {System.out.println("Unexpected data in file");System.exit(-1);}byte origDigest[] = (byte []) o;MessageDigest md = MessageDigest.getInstance("XYZ");md.update(data.getBytes());if (MessageDigest.isEqual(md.digest(), origDigest))System.out.println("Message is valid");else System.out.println("Message was corrupted");MessageDigest md2 = MessageDigest.getInstance("SHA");md2.update(data.getBytes());if (MessageDigest.isEqual(md2.digest(), origDigest))System.out.println("Message is valid");else System.out.println("Message was corrupted");ois.close();}
}

View Code

在这个用例中,writeMessage()将一段字符串保存后并将生成的digest也保存。

readMessage()将消息读取后,使用MessageDigest.isEqual()方法进行比较,这样可以知道文件是否被人改动过。

而实际上利用私钥更新签名信息时,就是使用MessageDigest#update()方法的。

4)Key 相关的服务

Key包括公钥(PublicKey)、私钥(PrivateKey)两种。

4.1 KeyPairGenerator

这个服务用于生成PublicKey和PrivateKey。

获取实例后,只需要根据上面4种initialize方法进行初始化后,就可以生成KeyPair了。

@Testpublic void generateKeyPair() throws Exception {// 算法名称有规定的值,不能乱写的KeyPairGenerator dsaKeyPairGenerator=KeyPairGenerator.getInstance("dsa");SecureRandom random=SecureRandom.getInstance("SHA1PRNG","SUN");random.setSeed(new byte[]{1,2,3,4});/*** jdk8: key必须在[512,1024]之间,并且是64的倍数。有的JDK版本要求是8的倍数,这要根据实际情况和需求设定*/dsaKeyPairGenerator.initialize(576, random);KeyPair keyPair=dsaKeyPairGenerator.generateKeyPair();DSAPublicKey puk=(DSAPublicKey)keyPair.getPublic();DSAPrivateKey pik=(DSAPrivateKey)keyPair.getPrivate();System.out.println(puk.getFormat());System.out.println(pik.getFormat());System.out.println(puk);System.out.println(pik);}

View Code

第一次调用generateKeyPair()都会生成不同的KeyPair。KeyPairGenerator 每次生成的都是一个KeyPair。

4.2 KeyFactory

KeyFactory用于在Key与KeySpec之间转换,即可以根据key获取到KeySpec,也可以根据KeySpec获取Key。

package com.fjn.security.key;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.DSAPublicKeySpec;import org.junit.Test;public class KeyFactoryTest {private static final String DSA="DSA";private static final String keyspecFile="keyspec.text";@Testpublic void genenatePublicKey() throws Exception{writeKeySpec();readKeySpec();}private void writeKeySpec() throws Exception {File file=new File(keyspecFile);file.deleteOnExit();file.createNewFile();KeyPairGenerator keyGen = KeyPairGenerator.getInstance(DSA);keyGen.initialize(512, new SecureRandom());KeyPair keyPair=keyGen.generateKeyPair();KeyFactory factory=KeyFactory.getInstance(DSA);DSAPublicKeySpec keySpec=factory.getKeySpec(keyPair.getPublic(), DSAPublicKeySpec.class);FileOutputStream fos = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(keySpec.getY());oos.writeObject(keySpec.getP());oos.writeObject(keySpec.getQ());oos.writeObject(keySpec.getG());oos.flush();oos.close();}private void readKeySpec() throws Exception {KeyFactory factory=KeyFactory.getInstance(DSA);FileInputStream fis = new FileInputStream(keyspecFile);ObjectInputStream ois = new ObjectInputStream(fis);DSAPublicKeySpec keySpec = new DSAPublicKeySpec((BigInteger) ois.readObject(),(BigInteger) ois.readObject(),(BigInteger) ois.readObject(),(BigInteger) ois.readObject());ois.close();PublicKey puk=factory.generatePublic(keySpec);System.out.println("Got private key:\n"+puk);}
}

View Code

5)Cert相关的服务

从上一篇的例子中知道,用户使用的Public Key有可能被不法分子偷偷地窜改,这样用户就得不到应有的服务,也会受到不法分子的危害。如何保证public key不被窜改或者替换呢?认证服务就出现了。

5.1 CertificateFactory

用于生成Certificate或者CRL的。

FileInputStream fis = new FileInputStream(filename);BufferedInputStream bis = new BufferedInputStream(fis);CertificateFactory cf = CertificateFactory.getInstance("X.509");while (bis.available() > 0) {Certificate cert = cf.generateCertificate(bis);System.out.println(cert.toString());}

什么是CRL ?

一个证书颁发机构需要证书吊销其颁发的证书——也许是虚假的,或者证书的用户已经使用证书从事非法行为。在这样的情况下,证书的有效期不足保护;证书必须立即失效。

下面的这个例子就是在验证完证书的有效性后,判断这个证书是否是一个吊销的证书。

public Certificate importCertificate(byte data[])throws CertificateException {X509Certificate c = null;try {CertificateFactory cf = CertificateFactory.getInstance("X509");ByteArrayInputStream bais = new ByteArrayInputStream(data);c = (X509Certificate) cf.generateCertificate(bais);Principal p = c.getIssuerDN();PublicKey pk = getPublicKey(p);c.verify(pk);InputStream crlFile = lookupCRLFile(p);cf = CertificateFactory.getInstance("X509CRL");X509CRL crl = (X509CRL) cf.generateCRL(crlFile);if (crl.isRevoked(c))throw new CertificateException("Certificate revoked");} catch (NoSuchAlgorithmException nsae) {throw new CertificateException("Can't verify certificate");} catch (NoSuchProviderException nspe) {throw new CertificateException("Can't verify certificate");} catch (SignatureException se) {throw new CertificateException("Can't verify certificate");} catch (InvalidKeyException ike) {throw new CertificateException("Can't verify certificate");} catch (CRLException ce) {// treat as no crl
    }return c;
}

View Code

5.2 CertPathBuilder构建证书链CertPath

CertPath就是之前说的证书链。其实就是一个Certificate的有序列表。在列表的最后的一个Cert是一个自签名的Cert。

5.3 CertPathValidator验证Cert链

CertPathValidator用于校验Cert。

6)KeyStore

一个KeyStore是一个key、cert的库,里面存储了PrivateKey, Aliases, Certs.

KeyStore将会有专门的说明。

7)Signature签名

用私钥签名,用公钥验证:

public class SignatureTest {@Testpublic void test() throws Exception{KeyPairGenerator keyPairGen=KeyPairGenerator.getInstance(Message.alogthem);keyPairGen.initialize(1024);KeyPair keyPair= keyPairGen.generateKeyPair();PublicKey puk=keyPair.getPublic();PrivateKey pik=keyPair.getPrivate();String data="Hello, Java.";Signature signature=Signature.getInstance("SHA1withDSA");// private key sign
        signature.initSign(pik);signature.update(data.getBytes());byte[] signinfo=signature.sign();// public key resolve sign
        signature.initVerify(puk);boolean ok=signature.verify(signinfo);System.out.println(ok);signature.update(data.getBytes());ok=signature.verify(signinfo);System.out.println(ok);}}

View Code

到此,JCA部分的engine class已经大体上有个了解了。接下来就是要学习如何应用它们了。

转载于:https://www.cnblogs.com/f1194361820/p/4262507.html

Java Security:Java加密框架(JCA)简要说明相关推荐

  1. java.security 框架之签名、加密、摘要及证书

      和第三方系统对接时,需要对隐私数据进行加密,对请求报文进行签名等.加密算法分为单向加密.对称加密.非对称加密等,其对应的算法也各式各样.Java 提供了统一的框架(java.security.*) ...

  2. java jca_Java加密体系结构(JCA)参考指南

    JCA简介 Java平台强调安全性,包括语言安全性.密码学.公钥基础设施.身份验证.安全通信和访问控制. JCA是java平台的重要部分,它包含了"provider"架构和一系列数 ...

  3. java 密码库_JCA-Java加密框架

    JCA是平台的一个主要部分,包含一个"Provider"体系结构和一组用于数字签名,消息摘要(哈希),证书和证书验证,加密(对称/非对称块/流密码),密钥生成 管理和安全随机数生成 ...

  4. java security用法_Java加密体系(一)java.security包

    一.JCA/ JCE JCA(Java Cryptography Architecture) 是Java体系结构,提供了基本Java加密框架,比如证书.数字签名.消息摘要.秘钥对生成器等,在java. ...

  5. Java加密体系-java.security包

    一.JCA/ JCE JCA(Java Cryptography Architecture) 是Java体系结构,提供了基本Java加密框架,比如证书.数字签名.消息摘要.秘钥对生成器等,在java. ...

  6. java加密框架_Java加密解密(一)Java加密体系基础

    标签: Java加密解密(一)Java加密体系基础 1. JCA(Java Cryptography Architecture) 提供基本的加密框架,如证书,数字签名,消息摘要和密钥对生成器.其主要实 ...

  7. AES加密时抛出java.security.InvalidKeyException:#160;Illegal#160;key#160;size#160;or#160;def...

    原文:AES加密时抛出java.security.InvalidKeyException: Illegal key size or def 使用AES加密时,当密钥大于128时,代码会抛出 java. ...

  8. 利用Java自带的MD5加密java.security.MessageDigest;

    MD5加密算法,即"Message-Digest Algorithm 5(信息-摘要算法)",它由MD2.MD3.MD4发展而来的一种单向函数算法(也就是HASH算法),它是国际著 ...

  9. Java之加密工具类java.security.MessageDigest或org.apache.commons.codec.digest.DigestUtils

    Java之加密(信息摘要)工具类(依赖:java.security.MessageDigest或org.apache.commons.codec.digest.DigestUtils) 1. java ...

最新文章

  1. 2021-05-09
  2. PyQt5 笔记1 -- 环境配置
  3. (递归3)最大公约数
  4. centos 6.0 rpm 包编译环境的搭建
  5. Java Lambda
  6. ArcGIS及ENVI软件下载链接(持续更新...)
  7. MAPGIS K9基础平台培训讲义——数据管理
  8. 沁春教你怎么在家制作拿铁咖啡!
  9. 投入产出表之直接消耗系数和完全消耗系数计算--基于Excel
  10. 前端学习路线(详细)
  11. c语言贾宗璞答案,c语言程序设计答案贾宗璞 许合利
  12. LocalSend 电脑和手机互传软件教程解答手机端无法搜索到电脑的解决方案
  13. 热电偶补偿导线的原理及必要性
  14. 【单片机毕业设计】【mcuclub-306】万年历电子时钟 | 数字时钟 | 多功能时钟 | 智能闹钟
  15. Python发送网易邮件554错误解决
  16. 前端物联网的起点 node-red 项目的开启
  17. 十年陌陌,是否能成为Hello
  18. 929. Unique Email Addresses*
  19. libnet编译linux,Linux 网络编程—— libnet 使用指南
  20. Android代码修改SIM的PIN码,中兴U970如何修改SIM卡或UIM卡的PIN码

热门文章

  1. 解决:Jackson反序列化Java内部类失败(序列化后的识别码为LinkedHashMap,而非内部类本身)
  2. 【历史上的今天】10 月 3 日:网络空间独立宣言之父诞生;3D 打印概念面世;eBay 收购 PayPal
  3. ZOJ Monthly,Feburary 2012 部分题解
  4. JMeter配置元件
  5. Kubernetes 安全专家(CKS)必过心得
  6. windows10应用程序需要设置管理员权限自启动
  7. 如何通过BIOS设置自动开机
  8. python怎么表示不等于_Python关系运算符中表示“不等于”的是哪个?________
  9. 提高沟通效果的十个技巧
  10. 《Real-Time Rendering》第四版学习笔记——Chapter 9 Physically Based Shading(二)