java jce-KeyGenerator(密钥生成)

java jce-KeyGenerator(密钥生成)

在开发时,总要涉及到数据的加密与解密,之前一直有些糊涂,最近看了 jce.jar的源码,来整理记录一下

接着上篇 java jce-Cipher(加密、解密) 来介绍一下 关于密钥生成的KeyGenerator

1、概念

JCA(Java Cryptography Architecture): Java密码体系结构

JCE(Java Cryptography Extension):它是一组包,提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现。它提供了对称、不对称、块和流密码的加密支持,并且还支持安全流和密封的对象,不对外出口,开发完成封装后将无法调用。

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

在JDK1.1-1.3版本期间,JCE属于扩展包,仅供美国和加拿大的用户下载,JDK1.4+版本后,JCE已经捆绑在JDK中,即jdk中的 jce.jar 包

1.1 加密算法

数据加密的基本过程就是对原来为明文的 文件 或 数据 按某种 算法 进行处理,使其成为不可读的一段代码为“密文”,使其只能在输入相应的 密钥 之后才能显示出原容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的,常见的加密算法,分为对称加密与非对称加密

1.1.1 对称式加密技术

加密和解密使用同一个密钥,通常称之为“Session Key ” ,如美国政府所采用的 DES 加密标准就是一种典型的 对称式加密法,它的Session Key长度为56bits

请添加图片描述

1.1.2 非对称式加密技术

加密和解密所使用的不是同一个密钥,通常有两个密钥,称为**“公钥”“私钥”,它们两个必需配对使用**,否则不能打开加密文件

“公钥”是指可以对外公布的,“私钥”则不能,只能由持有人一个人知道。它的优越性就在这里,因为对称式的加密方法如果是在网络上传输加密文件就很难不把密钥告诉对方,不管用什么方法都有可能被别人窃听到。而非对称式的加密方法有两个密钥,且其中的“公钥”是可以公开的,也就不怕别人知道,收件人解密时只要用自己的私钥即可以,这样就很好地避免了密钥的传输安全性问题

请添加图片描述

1.1.3 常用的加密算法
算法名称密钥长块长速度说明类型
DES5664较快适用于加密大量数据,不太安全对称加密
3DES112/16864较慢中等安全, 适合加密较小的数据对称加密
AES128, 192, 256128安全对称加密
Blowfish(4至56)*864应该安全, 在安全界尚未被充分分析、论证对称加密
RC440-102464很快安全性不明确,变长密钥对大量数据进行加密对称加密
RSA500-1024很慢512位被视为不安全的;768位不用担心受到危害;1024位几乎是安全的,用于少量数据加密非对称加密
MD512832普遍、稳定广泛应用于普通数据,不可逆散列算法
SHA1160安全散列算法,但安全性如今被密码学家严重质疑散列算法

总结:

  • 非对称加密普遍会比对称加密慢,取决于密码长度(长度长计算复杂度大)
  • 非对称加密普遍使用RSA,对称加密普遍使用AES
  • 对称加密的密钥管理较为重要,需要保证传输的安全性
  • 散列算法的安全性不高,有被破解的可能

2、核心类与核心方法

以jdk 1.8 为例进行下面的说明

jce.jar 包的核心API都在 javax.crypto 包下,主要包括:加解密、密钥生成(对称)、MAC生成、密钥协商等核心功能

请添加图片描述

核心的一些类/接口如下:

这篇介绍KeyGenerator

KeyGenerator

该类主要用于生成密钥

  • 在Cipher 初始化的时候,可以指定密钥 Key,而该Key的具体生成可由该类实现

请添加图片描述

主要由以下方法:

  • getInstance:创建一个KeyGenerator对象
  • init:KeyGenerator对象初始化
  • generateKey:生成密钥

下面详细说明:

1 getInstance:创建一个KeyGenerator对象

根据以下三种重载方法获取到一个KeyGenerator对象(与Cipher的创建雷同)

// algorithm 是 算法名称   
public static final Cipher getInstance(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {
}
// provider 是具体的 provider name   java.security.Security 根据name获取Prvider
public static final Cipher getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
}
// provider 是具体的provider
public static final Cipher getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException {
}

说明:

1)这里的算法名称与Cipher有些不同,其只有一种表示方式,就是算法名称,而不像Cipher有 “algorithm/mode/padding” 的形式表示

algorithm取值:

  • AES / AESWrap
  • ARCFOUR
  • Blowfish
  • RC2 / RC4 / RC5
  • RSA
  • DES / DESede / DESedeWrap / ECIES
2 init:KeyGenerator对象初始化

根据以下几种重载方法进行KeyGenerator对象初始化

// random :随机数发生器
public void init(SecureRandom random);
// keysize:密钥长度
public void init(int keysize);

public void init(int keysize, SecureRandom random);

// params:加密参数
public void init(AlgorithmParameterSpec params);

public void init(AlgorithmParameterSpec params, SecureRandom random);

说明:

  • SecureRandom:随机数发生器,它产生加密强随机数。如果生成器中的随机性不足,则更容易破坏保护机制,一般可使用相同的种子来生成相同的随机数,保证密钥是相同的,如果不指定,默认每次都是不带随机种子的 new SecureRandom()
  • keySize:这个根据使用的加密算法,来指定密钥的长度
  • AlgorithmParameterSpec :加密参数透明规范的接口,一般 像有些加密算法,第一个消息加密的时候是需要 初始化向量IV,那么就可以借助 IvParameterSpec来定义一个初始化向量,以这个参数传入

Cipher有4种操作模式(即var1有四种取值):

  • ENCRYPT_MODE:加密
  • DECRYPT_MODE:解密
  • WRAP_MODE:将key包装成字节,以便可以安全地传输密钥,导出Key
  • UNWRAP_MODE:将以前包装的密钥解包到key中,导入Key
3 generateKey:生成密钥

通过上述创建好并且初始化好的KeyGenerator对象进行密钥的创建

// 生成密钥
public SecretKey generateKey();
4 举例

使用流程:

  1. 创建
  2. 初始化
  3. 生成密钥

example:

private static Key getKey(String strKey) throws NoSuchAlgorithmException {
    	// 1.创建
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        // 2. 初始化
        keyGenerator.init(128 ,new SecureRandom(strKey.getBytes()));
    	// 3、生成密钥
        SecretKey secretKey = keyGenerator.generateKey();
        return secretKey;
}

相关链接

1、JCA

java JCA参考指南

Java密体系结构标准算法文档

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java生成密钥的实例    //产生单钥加密的密钥(myKey)   KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede"); //采用DESede算法   keyGenerator.init(168); //选择DESede算法,密钥长度为112位或168位   Key myKey = keyGenerator.generateKey(); //生成密钥   System.out.println("得到单钥加密密钥");   //产生双钥的密钥对(keyPair)   KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA"); //采用RSA算法   keyPairGenerator.initialize(1024); //指定密钥长度为1024位   KeyPair keyPair = keyPairGenerator.generateKeyPair(); //生成密钥对   System.out.println("生成张三的公钥对");   //保存公钥的字节数组   File f = new File("publicKey.dat"); //保存公钥到文件publicKey.dat   FileOutputStream fout = new FileOutputStream(f);   fout.write(keyPair.getPublic().getEncoded()); //得到公钥的字节数组   fout.close(); //关闭文件输出流   System.out.println("保存公钥到文件: " f.getAbsolutePath());   //用Java对象序列化保存私钥,通常应对私钥加密后再保存   ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream("privateKey.dat")); //保存私钥到文件privateKey.dat   oout.writeObject(keyPair.getPrivate()); //序列化私钥   oout.close(); //关闭输出流   System.err.println("保存私钥到: privateKey.dat");   //从文件中得到公钥编码的字节数组   FileInputStream fin = new FileInputStream("publicKey.dat"); //打天publicKey.dat   ByteArrayOutputStream baout = new ByteArrayOutputStream(); //用于写入文件的字节流   int aByte = 0;   while ((aByte = fin.read())!= -1) //从文件读取一个字节   {    baout.write(aByte); //写入一个字节   }   fin.close(); //关闭文件输入流   byte[] keyBytes = baout.toByteArray(); //得到公钥的字节数组   baout.close(); //关闭字节数组输出流
下面是Java代码示例,可以用于随机生成SM4密钥: ```java import org.bouncycastle.crypto.generators.SCrypt; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.SCryptParameters; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.Security; public class SM4KeyGenerator { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException { Security.addProvider(new BouncyCastleProvider()); KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4", "BC"); SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt); SCryptParameters params = new SCryptParameters(16384, 8, 1, salt); byte[] key = SCrypt.generate("password".getBytes(), salt, params); keyGenerator.init(128, new SecureRandom(key)); SecretKey secretKey = keyGenerator.generateKey(); byte[] keyBytes = secretKey.getEncoded(); System.out.println("SM4 key: " + bytesToHexString(keyBytes)); } private static String bytesToHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(b & 0xFF); if (hex.length() < 2) { sb.append(0); } sb.append(hex); } return sb.toString(); } } ``` 此代码使用BouncyCastle提供的SCrypt算法生成指定密码的密钥,然后使用SM4算法生成128位的随机密钥。请注意,此代码仅用于学习和测试目的。在实际应用中,请使用更安全的随机数生成器和更复杂的密码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值