彻底告别加解密模块代码拷贝(3)

7、SECRET_KEY,整型值3,解包装密钥模式下指定密钥类型为密钥,主要用于不是非对称加密的密钥(只有一个密钥,不包含私钥和公钥)。

Cipher的主要方法 getInstance方法

Cipher提供三个静态工厂方法getInstance用于构建其实例,三个方法如下:

public static final Cipher getInstance(String transformation) throws NoSuchAlgorithmException, NoSuchPaddingException public static final Cipher getInstance(String transformation, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException public static final Cipher getInstance(String transformation, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException

其中transformation,这里称为转换(模式),是核心参数,见前面一个小节的解析。另外,有两个工厂方法要求必须传入java.security.Provider的全类名或者实例,因为Cipher要从对应的提供商中获取指定转换模式的实现,第一个工厂方法只有单参数transformation,它会从现成所有的java.security.Provider中匹配取出第一个满足transformation的服务,从中实例化CipherSpi(要理解Cipher委托到内部持有的CipherSpi实例完成具体的加解密功能)。实际上Cipher实例的初始化必须依赖于转换模式和提供商。

init方法

init方法一共有八个变体方法,此方法主要用于初始化Cipher。

//额外参数是Key(密钥) public final void init(int opmode, Key key) throws InvalidKeyException //额外参数是Key(密钥)和SecureRandom(随机源) public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException //额外参数是Key(密钥)和AlgorithmParameterSpec(算法参数透明定义) public final void init(int opmode, Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException //额外参数是Key(密钥)、AlgorithmParameterSpec(算法参数透明定义)和SecureRandom(随机源) public final void init(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException //额外参数是Key(密钥)、AlgorithmParameters(算法参数) public final void init(int opmode, Key key, AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException //额外参数是Key(密钥)、AlgorithmParameters(算法参数)、SecureRandom(随机源) public final void init(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException //额外参数是Certificate(证书) public final void init(int opmode, Certificate certificate) throws InvalidKeyException //额外参数是Certificate(证书)、SecureRandom(随机源) public final void init(int opmode, Certificate certificate, SecureRandom random) throws InvalidKeyException

opmode(操作模式)是必须参数,可选值是ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE和UNWRAP_MODE。Key类型参数如果不是非对称加密,对应的类型是SecretKey,如果是非对称加密,可以是PublicKey或者PrivateKey。SecureRandom是随机源,因为有些算法需要每次加密结果都不相同,这个时候需要依赖系统或者传入的随机源,一些要求每次加解密结果相同的算法如AES不能使用此参数。Certificate是带有密钥的证书实现。算法参数主要包括IV(initialization vector,初始化向量)等等。

wrap方法和unwrap方法

wrap方法用于包装一个密钥。

public final byte[] wrap(Key key) throws IllegalBlockSizeException, InvalidKeyException

wrap方法使用的时候需要注意Cipher的opmode要初始化为WRAP_MODE。

unwrap方法用于解包装一个密钥。

public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException

unwrap方法使用的时候需要注意Cipher的opmode要初始化为UNWRAP_MODE,在调用unwrap方法时候,需要指定之前包装密钥的算法和Key的类型。

其实wrap和unwrap是一个互逆的操作:

wrap方法的作用是把原始的密钥通过某种加密算法包装为加密后的密钥,这样就可以避免在传递密钥的时候泄漏了密钥的明文。

unwrap方法的作用是把包装(加密)后的密钥解包装为原始的密钥,得到密钥的明文。

public enum EncryptUtils { /** * 单例 */ SINGLETON; private static final String SECRECT = "passwrod"; public String wrap(String keyString) throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); //初始化密钥生成器,指定密钥长度为128,指定随机源的种子为指定的密钥(这里是"passward") keyGenerator.init(128, new SecureRandom(SECRECT.getBytes())); SecretKey secretKey = keyGenerator.generateKey(); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.WRAP_MODE, secretKeySpec); SecretKeySpec key = new SecretKeySpec(keyString.getBytes(), "AES"); byte[] bytes = cipher.wrap(key); return Hex.encodeHexString(bytes); } public String unwrap(String keyString) throws Exception { byte[] rawKey = Hex.decodeHex(keyString); KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); //初始化密钥生成器,指定密钥长度为128,指定随机源的种子为指定的密钥(这里是"passward") keyGenerator.init(128, new SecureRandom(SECRECT.getBytes())); SecretKey secretKey = keyGenerator.generateKey(); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.UNWRAP_MODE, secretKeySpec); SecretKey key = (SecretKey) cipher.unwrap(rawKey, "AES", Cipher.SECRET_KEY); return new String(key.getEncoded()); } public static void main(String[] args) throws Exception { String wrapKey = EncryptUtils.SINGLETON.wrap("doge"); System.out.println(wrapKey); System.out.println(EncryptUtils.SINGLETON.unwrap(wrapKey)); } }

上面的例子是通过AES对密钥进行包装和解包装,调用main方法,输出:

77050742188d4b97a1d401db902b864d doge update方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/b5e4d8f6f0ddf4f7771d5bbfc73289c8.html