JAVA加密

JAVA加密

JCA: Java密码体系结构Java Cryptography Architecture(这里基本上就是规范)
JCE(Java Cryptography Extension)基于以上结构体系作出的实现等扩展
---------------------分割线--------------------------------------

1.加签验签相关

主要类
Signature 类
该类有3种状态
1.UNINITIALIZED
2.SIGN
3.VERIFY

第一步

Signature dsa = Signature.getInstance(“SHA256withDSA”);
该字符串为特定字符串,官方文档中有标准格式,指定了签名算法,第一步之后,处于未初始化状态

第二步

dsa.initSign(priv);或者dsa.initVerify(pub);
根据需要(加签还是验签)进行初始化状态,其中加签使用PrivateKey 密钥 验签使用PublicKey 公钥

第三步

dsa.update(data);
该参数为原始的数据,无论是加签还是验签,都要进行这一步

第四步

byte[] sig = dsa.sign();或者boolean verifies = dsa.verify(sig);
加签或者进行验签

补充

以上即为签名主要过程,区别和用法主要在使用的算法不同,以及如何获取密钥(公钥或者私钥)
initVerify(Certificate certificate)验签可以使用证书
update(byte[] data, int off, int len)updata过程也可以多次调用以免data过大
也可以有在签名的时候提供指定的字节数组,或者验签的时候指定字节数组
------------------------分割线-----------------------------------------------------------

2.加密解密相关

主要类为Cipher

第一步

Cipher c1 = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
这里的字符串同加签验签,官方提供了标准的内容。当然也可以自己实现在AES算法中,需要指定加密时的mode(即上面的ECB)以及数据长度不符合标准时的填充方式即上面指定的PKCS5Padding 在使用的时候也可以不指定,例如
Cipher c1 = Cipher.getInstance(“AES”);
此时由加密算法的底层实现提供默认的mode和填充方式,因此根据底层实现不同,默认值也可能不同,例如SunJCE and SunPKCS11 providers uses ECB as the default mode, and PKCS5Padding as the default padding for many symmetric ciphers.

第二步

c1.init(Cipher.ENCRYPT_MODE, aesKey);
初始化,根据加密还是解密,来进行初始化。第二个参数为对称加密算法所用的密钥
当然也可以使用证书
init(int opmode, Certificate certificate);
指定随机数
init(int opmode, Key key, SecureRandom random);
等等方式

第三步

byte[] ciphertext = aesCipher.doFinal(Text);
进行加密,得到密文字节码

补充

加密解密不仅仅可以对完整的字节数据(参数为字节数组)进行,还可以对输入输出流进行加密解密
-----------------------------分割线---------------------------

3.密钥

在以上加签验签以及加密解密中,都使用了密钥,在JAVA中,密钥的获取也是非常关键对于加签验签来说,主要就是PrivateKey和PublicKey对象的获取,对于加密来说主要就是Key对象的获取,当然 加密解密也是可以使用非对称的RSA算法的(上面的例子使用的是AES对称算法)。
主要接口Key

1.如何拿到Key/如何生成Key

总的来讲分为:1.生成器 2.KeyFactory工厂类+KeySpec接口实现类 3.证书 4.KeyStore(密钥库) 5.字节数据

2.详解

1.生成器方式
--------非对称加密算法生成器分割线-------
使用 KeyPairGenerator 类 生成非对称加密加密算法的密钥
第一步
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(“DSA”);
同前所述,这里也有标准的参数,分别对应不同的算法需求的密钥
第二步
keyGen.initialize(2048);
这里的Size是各种加密算法中描述的密钥长度
我们也可以使用特殊的密钥生成种子来进行生成密钥
SecureRandom random = SecureRandom.getInstance(“DRBG”, “SUN”);
random.setSeed(userSeed);
keyGen.initialize(2048, random);
在上面的初始化过程中,并没有指定Key在生成过程中需要什么参数,因此,这些参数就取决于我们所使用的底层加密包
DSAParameterSpec dsaSpec = new DSAParameterSpec(p, q, g);
keyGen.initialize(dsaSpec);
当我们指定了某种算法的Key的生成参数,那么就会按照的约定的参数来进行Key的生成工作
DSAParameterSpec是实现了AlgorithmParameterSpec接口的某种特定算法的参数类同样的也有别的例如DHParameterSpec这种参数类
第三步
KeyPair pair = keyGen.generateKeyPair();
到此就结束了Key的生成,通过调用KeyPair的各种方法,我们就可以拿到公钥或者私钥了。
以上使用的生成器,生成的是非对称加密算法的密钥,对称加密算法的密钥也是用类似的方式,但是生成器不同
--------非对称加密算法生成器分割线-----对称加密算法生成器分割线------
KeyGenerator 类 生成非对称加密加密算法的密钥
第一步
KeyGenerator keygen = KeyGenerator.getInstance(“AES”);
第二步
SecretKey aesKey = keygen.generateKey();
这里拿到的SecretKey接口 集成了 Key接口,因此可以用在加密解密的Cipher类中。对称加密生成器当然也可以像非对称一样通过参数类来详细指定Key的生成过程,或者底层提供者(getInstance的第二个参数可以指定底层实现的提供者)但是在对称算法中,这些好像不是特别重要
-----------对称加密算法生成器分割线--------
2.KeyFactory工厂+KeySpec接口实现类
KeyFactory是不能单独进行Key的生成,这个工厂类的主要作用是进行类型转换
首先我们回到上面所述的,在密钥部分的重要接口Key。这个Key接口只是粗略的规定了一个密钥应该做的方法,但是并没有指定该密钥的具体算法
因此我们还有一个重要的接口 KeySpec 接口,该接口没有规定的方法,只是用来管理和标识某个Key是具体的Key而不是粗略的
该接口的实现类例如:DESKeySpec等都是一种特定算法的实现类,明确规定了该算法下的Key应该具体实现的一些方法,比Key规定的粗略的方法具体很多。
说完了这两个原始概念不同的接口Key以及KeySpec,结合我们的加密类Cipher使用的都是Key接口下的密钥,因此需要一种转换类将KeySpec转换为Key。这就是KeyFactory的作用了。根据对称加密算法和非对称加密算法的不同,Factory类也分为KeyFactory类以及SecretKeyFactory类,分别对应了非对称和对称(带Secret的一般都是对称,因为对称的得保密,而非对称的可以公开一半)
接下来,明确了工厂类的作用是把KeySpec转换为Key,这样我们就能使用加密类,那么我们该如何得到KeySpec呢
方法如下:
DESedeKeySpec desEdeKeySpec = new DESedeKeySpec(desEdeKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstanc(“DESede”);
SecretKey secretKey = keyFactory.generateSecret(desEdeKeySpec);
通过这样的方式,我们就可以得到一个完整的密钥了。
用RSA的方式举例的话,如下:
RSAPublicKeySpec rsaPublicKeySpec =
new RSAPublicKeySpec(new BigInteger(String.valueOf(1)),new BigInteger(String.valueOf(2)));
通过指定RSA算法中的模和幂,我们就可以拿到指定的RSA密钥。每个算法都有自己的生成参数。
在实践中,我们可以通过指定详细参数的方式从无到有生成配对的密钥,这相当于我们从密码学上手动把密钥算出来了而已。
整个KeyFactory的体系,把是给定已经存在的,算好的密钥参数,拿到能用的Key接口的实现类。
两种Factory的使用方式都很简单,如下
KeyFactory keyFactory = KeyFactory.getInstance(“xx”);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(“XX”);
对象方法也很简单,这里就不列举了。
-------------------------------------分割线-------------------------------------------
3.证书方式
证书其实不是加密体系的东西,证书在JAVA中有自己的体系。但是在证书的最大作用就是用来存放密钥,并且在实践中也确实有很重要的作用。
证书还要牵扯到JAVA的PKI所以这里只是简单的说说
证书的编码格式基本分为 PER DER
区别只是Base64 和 Ascii
后缀分为CRT CER (这两个都是放的公钥) KEY CSR PFX/P12 这些都是证书
CRT 应该是 certificate 的三个字母,其实还是证书的意思。常见于 UNIX 系统,有可能是 PEM 编码,也有可能是 DER 编码,大多数应该是 PEM 编码
CER还是 certificate,还是证书。常见于 Windows 系统,同样的可能是 PEM 编码,也可能是 DER 编码,大多数应该是 DER 编码
KEY 通常用来存放一个公钥或者私钥,并非 X.509 证书。编码同样的,可能是 PEM,也可能是 DER。
CSRCertificate,Signing Request,即证书签名请求。这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息)。
PFX/P12 redecessor of PKCS#12,对 unix 服务器来说,一般 CRT 和 KEY 是分开存放在不同文件中的,但 Windows 的 IIS 则将它们存在一个 PFX 文件中,(因此这个文件包含了证书及私钥)PFX 通常会有一个“提取密码”,你想把里面的东西读取出来的话,它就要求你提供提取密码
Ruo_Xiao博主写的很好,快去看!
https://blog.csdn.net/itworld123/article/details/115553346
首先来一把
CertificateFactory c = CertificateFactory.getInstance(“X.509”)(手撸的可能有误,但是是这个流程)
调用generateCertificate(InputStream inStream)拿到Certificate 证书对象
输入流就是你的证书输入流,然后从证书对象里面就可以通过方法拿到字节数据,或者直接拿到公钥,看证书类型了。
拿到了字节数据之后就可以去5看看,然后就有Key,然后就可以使用了
-------------------------------------分割线-------------------------------------------
4.密钥库
密钥库通常都是有密码的,也是有格式类型的
例如jks,pkcs12这两个类型的比较常见
仍然用 KeyStore getInstance() 拿到对象
load(InputStream stream, char[] password)用这个方法连接具体的密钥库文件
aliases() 用这个获得全部密钥的别名
getCertificate(String alias)拿到证书,然后就可以进行下一步了
还有一些其他的方法,可以备用,比如对密钥的增删改查之类
或者还有其他的方法,这里就不详细列举了
-------------------------------------分割线-------------------------------------------

5.字节数据
在继承了Key接口的密钥实现类,都实现了获得密钥编码的方法,改方法可以让你获取到密钥的字节数据,当你拿到密钥的自己数据以后,就可以用这里的方法,通过这些字节数据来获取密钥类
这里只说非对称的加密方式
PKCS8EncodedKeySpec 类用来表示私钥(DER编码方式)
X509EncodedKeySpec 类用来表示公钥(DER编码方式)
相关标准分别为PKCS8和X.509
这两个类的构造方式也很简单,new 关键字声明这个类,然后参数为密钥的字节数组即可使用
配合工厂类就能拿到Key接口的密钥类,然后就能使用在签名,验签上面了。
----------------------------------分割线---------------------------
java提供了KeyTool文件可以生成证书文件,你也可以用最上面的生成器代码进行生成,然后打出来编码后的密钥,生成器生成的密钥都是集成了Key的密钥,实现了get(有个拿编码的方法)
-----------------------------------一些示例代码------------------------
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());
}

----------------------------一些示例代码------------------------

DSAPrivateKeySpec dsaPrivKeySpec = new DSAPrivateKeySpec(x, p, q, g);

KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PrivateKey privKey = keyFactory.generatePrivate(dsaPrivKeySpec);

Signature sig = Signature.getInstance("SHA256withDSA");
sig.initSign(privKey);
sig.update(someData);
byte[] signature = sig.sign();

----------------------一些示例代码----------------------

X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodedPubKey);

KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

Signature sig = Signature.getInstance("SHA256withDSA");
sig.initVerify(pubKey);
sig.update(data);
sig.verify(signature);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值