Java安全 – JCE Blowfish算法报错
代码里用Blowfish算法加解密,结果jdk升到1.7后算法初始化失败
java.lang.RuntimeException: java.lang.RuntimeException: PANIC: Unreachable code reached.
JCE不熟悉,更新到原来jdk6的security后报
java.lang.SecurityException: The jurisdiction policy files are not signed by a trusted signer
解决方法:
单独下载JCE 扩展:需单独从Oracle官网下载对应JDK版本的Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files
JDK7对应的jurisdiction policy files:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
jdk6
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JCE,Java Cryptography Extension,在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。在JDK1.1-1.3版本期间,JCE属于扩展包,仅供美国和加拿大的用户下载,JDK1.4+版本后,随JDK核心包一起分发;
JCA和JCE的API体系架构
JCE的API都在javax.crypto包下,核心功能包括:加解密、密钥生成(对称)、MAC生成、密钥协商,下面我们就详细介绍下这些功能。
一. 加解密
加解密功能由Cipher组件提供,其也是JCE中最核心的组件。
1. Cipher的几个知识点:
——————————————————————————————–
a. Cipher在使用时需以参数方式指定transformation
b. transformation的格式为algorithm/mode/padding,其中algorithm为必输项,如: DES/CBC/PKCS5Padding
c. 缺省的mode为ECB,缺省的padding为PKCS5Padding
d. 在block算法与流加密模式组合时, 需在mode后面指定每次处理的bit数, 如DES/CFB8/NoPadding, 如未指定则使用缺省值, SunJCE缺省值为64bits
e. Cipher有4种操作模式: ENCRYPT_MODE(加密), DECRYPT_MODE(解密), WRAP_MODE(导出Key), UNWRAP_MODE(导入Key),初始化时需指定某种操作模式
2. 对称加密的算法与密钥长度选择
算法名称 | 密钥长 | 块长 | 速度 | 说明 |
---|---|---|---|---|
DES | 56 | 64 | 慢 | 不安全, 不要使用 |
3DES | 112/168 | 64 | 很慢 | 中等安全, 适合加密较小的数据 |
AES | 128, 192, 256 | 128 | 快 | 安全 |
Blowfish | (4至56)*8 | 64 | 快 | 应该安全, 在安全界尚未被充分分析、论证 |
RC4 | 40-1024 | 64 | 很快 | 安全性不明确 |
一般情况下,不要选择DES算法,推荐使用AES算法。一般认为128bits的密钥已足够安全,如果可以请选择256bits的密钥。注意:
——————————————————————————————–
a. 密钥长度是在生成密钥时指定的,如:
KeyGenerator generator = KeyGenerator.getInstance("AES/CBC/PKCS5PADDING");
generator.init(256);
SecretKey key = generator.generateKey();
b. 生成长度超128bits的密钥,需单独从Oracle官网下载对应JDK版本的Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files文件,例如JDK7对应的jurisdiction policy files
3. 加密示例代码
/**
* 根据密钥{@link #getKey()}对指定的明文plainText进行加密.
*
* @param plainText 明文
* @return 加密后的密文.
*/
public static final String encrypt(String plainText) {
Key secretKey = getKey();
try {
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] p = plainText.getBytes("UTF-8");
byte[] result = cipher.doFinal(p);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(result);
return encoded;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
4. 解密示例代码
/**
* 根据密钥{@link #getKey()}对指定的密文cipherText进行解密.
*
* @param cipherText 密文
* @return 解密后的明文.
*/
public static final String decrypt(String cipherText) {
Key secretKey = getKey();
try {
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
BASE64Decoder decoder = new BASE64Decoder();
byte[] c = decoder.decodeBuffer(cipherText);
byte[] result = cipher.doFinal(c);
String plainText = new String(result, "UTF-8");
return plainText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
5. 带算法参数的加解密
Cipher可能用到算法参数(AlgorithmParameterSpec或AlgorithmParameters)的情形:
——————————————————————————————–
a. DES, DES-EDE, and Blowfish使用feedback模式时(如CBC, CFB, OFB或PCBC), 将用到IV
b. PBEWithMD5AndDES将用到salt和iteration count
下面是采用PBE算法进行加解密的示例:
/**
* 提供基于口令的加密功能.
*
* @param plainText 明文
* @return 加密后的密文.
*/
public static final String pbeEncrypt(String plainText) {
Key pbeSecretKey = getPBEKey();
PBEParameterSpec pbeParamSpec = getParamSpec();
try {
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, pbeSecretKey, pbeParamSpec);
byte[] p = plainText.getBytes("UTF-8");
byte[] result = cipher.doFinal(p);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(result);
return encoded;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 提供基于口令的解密功能.
*
* @param cipherText 密文
* @return 解密后的明文.
*/
public static final String pbeDecrypt(String cipherText) {
Key pbeSecretKey = getPBEKey();
PBEParameterSpec pbeParamSpec = getParamSpec();
try {
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.DECRYPT_MODE, pbeSecretKey, pbeParamSpec);
BASE64Decoder decoder = new BASE64Decoder();
byte[] c = decoder.decodeBuffer(cipherText);
byte[] result = cipher.doFinal(c);
String plainText = new String(result, "UTF-8");
return plainText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 获取PBE算法的密钥. 注意PBE密钥由用户提供的口令构造出来的,
* 用户提供的口令务必使用char数组, 而不能使用字符串, 字符数
* 组用完即清空.
*
* @return PBE算法的密钥.
*/
private static final Key getPBEKey() {
// TODO come from db or System.in, NOTE: MUST be char array, not java.lang.String
char[] pwd = {'%', '_', 'A', 's', '9', 'K'};
SecretKey pbeKey = null;
PBEKeySpec pbeKeySpec = new PBEKeySpec(pwd);
try {
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
pbeKey = keyFac.generateSecret(pbeKeySpec);
return pbeKey;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
Arrays.fill(pwd, ' ');
}
}
/**
* 获取PBE的算法参数, 涉及salt和iterate count两个参数.
*
* @return PBE的算法参数.
*/
private static final PBEParameterSpec getParamSpec() {
byte[] salt = { (byte) 0xab, (byte) 0x58, (byte) 0xa1, (byte) 0x8c,
(byte) 0x3e, (byte) 0xc8, (byte) 0x9d, (byte) 0x7a };
int count = 20;
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, count);
return paramSpec;
}
测试代码:
String pbePlainText = "127Kjk$%2^";
String pbeCipherText = pbeEncrypt(pbePlainText);
String pbePlainText2 = pbeDecrypt(pbeCipherText);
if (!pbePlainText.equals(pbePlainText2)) {
System.out.println("PBE Something wrong");
}
二. 密钥生成
非对称密钥的生成请参考java.security.KeyPairGenerator,样例代码请参考JCA中的示例,对称密钥生成的示例代码如下:
KeyGenerator gen = KeyGenerator.getInstance("DES");
gen.init(56, new SecureRandom());
Key key= gen.generateKey();
三. MAC生成
MAC技术用于确认数据的完整性,Mac要求通讯双方共享一个secret key,示例代码如下:
Key key = KeyGeneratorDemo.generateMac();
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
String msg = "新庄杨渡10#";
byte[] result = mac.doFinal(msg.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
System.out.println(encoder.encode(result));
MAC优于数据摘要的地方在于:MAC双方要共享一个密钥,所以其也有互相认证的功能,可有效防止数据摘要中明文和数据摘要被同时替换而无法发现的问题。
四. 密钥协商
密钥协商就是在通讯多方间不直接交换通讯密钥的情况下而选择一个大家达成一致的密钥(session key),这个session key是对称密钥。
1. 密钥协商可以通过2种途径实现:
——————————————————————————————–
a. 通过KeyAgreement组件完成,常用算法包括DH(Diffie-Hellman),ECDH(Elliptic Curve Diffie-Hellman),ECMQV(Elliptic Curve Menezes-Qu-Vanstone)等。
b. 通过数字信封完成,常用算法包括RSA等。
2. 通过KeyAgreement使用DH算法协商密钥
a. DH算法由PKCS#3定义,DH算法需在多方间交换公钥,大素数p,私钥的基数g,和私钥的长度l。设协商密钥的双方为Alice和Bob,则协商共涉及5个阶段:
——————————————————————————————–
i. Alice生成DH公私密钥对
ii. Alice将公钥和算法参数p,g和l发送给Bob
iii. Bob根据算法参数生成自己的公私密钥对,并将公钥发送给Alice
iv. Alice使用自己的私钥和Bob的公钥通过KeyAgreement得到通讯密钥
v. Bob使用自己的私钥和Alice的公钥通过KeyAgreement得到与Alice相同的通讯密钥
b. 下面的代码演示了使用DH算法实现密钥协商,设通讯一方为Alice,另一方为Bob,分别由两个线程模拟,实际数据交换由共享内存模拟:
/*
* @(#)KeyAgreementDemo.java 1.0 2012-4-24
*
* Copyright 2010 Richard Chen(utopia_rabbi@sse.buaa.edu.cn) All Rights Reserved.
* PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package charpter.security.keyagreement;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DHParameterSpec;
/**
* 演示Deffie-Hellman密钥交换组件的用法.
*
* 密钥交换就是在通讯多方间不直接交换通讯密钥的情况下而选择一个大家达成一致的密钥.
*
* @author Rich, 2012-4-24.
* @version 1.0
* @since 1.0
*/
public class KeyAgreementDemo implements Runnable {
/** bob和alice的公钥内容. */
byte bob[], alice[];
/** alice侧是交换的发起方, 是否已启动. */
boolean doneAlice = false;
/** 使用计算出来的交换密钥加密过的报文. */
byte[] ciphertext;
/** DH算法涉及的算法参数, alice侧的大素数p, alice侧的私钥基数g. */
BigInteger aliceP, aliceG;
/** DH算法涉及的算法参数, alice的私钥长度l. */
int aliceL;
public synchronized void run() {
if (!doneAlice) {
doAlice();
doneAlice = true;
} else
doBob();
}
public synchronized void doAlice() {
try {
// Step 1: Alice generates a key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
// Step 2: Alice sends the public key and the
// Diffie-Hellman key parameters to Bob
Class dhClass = Class.forName("javax.crypto.spec.DHParameterSpec");
DHParameterSpec dhSpec = ((DHPublicKey) kp.getPublic()).getParams();
aliceG = dhSpec.getG();
aliceP = dhSpec.getP();
aliceL = dhSpec.getL();
alice = kp.getPublic().getEncoded();
notify();
// Step 4 part 1: Alice performs the first phase of the
// protocol with her private key
KeyAgreement ka = KeyAgreement.getInstance("DH");
ka.init(kp.getPrivate());
// Step 4 part 2: Alice performs the second phase of the
// protocol with Bob's public key
while (bob == null) {
wait();
}
KeyFactory kf = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(bob);
PublicKey pk = kf.generatePublic(x509Spec);
ka.doPhase(pk, true);
// Step 4 part 3: Alice can generate the secret key
byte secret[] = ka.generateSecret();
// Step 6: Alice converts a secret key
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
DESKeySpec desSpec = new DESKeySpec(secret);
SecretKey key = skf.generateSecret(desSpec);
// Step 7: Alice encrypts data with the key and sends
// the encrypted data to Bob
Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key);
ciphertext = c.doFinal("Stand and unfold yourself".getBytes());
notify();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void doBob() {
try {
// Step 3: Bob uses the parameters supplied by Alice
// to generate a key pair and sends the public key
while (alice == null) {
wait();
}
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
DHParameterSpec dhSpec = new DHParameterSpec(aliceP, aliceG, aliceL);
kpg.initialize(dhSpec);
KeyPair kp = kpg.generateKeyPair();
bob = kp.getPublic().getEncoded();
notify();
// Step 5 part 1: Bob uses his private key to perform the
// first phase of the protocol
KeyAgreement ka = KeyAgreement.getInstance("DH");
ka.init(kp.getPrivate());
// Step 5 part 2: Bob uses Alice's public key to perform
// the second phase of the protocol.
KeyFactory kf = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(alice);
PublicKey pk = kf.generatePublic(x509Spec);
ka.doPhase(pk, true);
// Step 5 part 3: Bob generates the secret key
byte secret[] = ka.generateSecret();
// Step 6: Bob generates a DES key
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
DESKeySpec desSpec = new DESKeySpec(secret);
SecretKey key = skf.generateSecret(desSpec);
// Step 8: Bob receives the encrypted text and decrypts it
Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key);
while (ciphertext == null) {
wait();
}
byte plaintext[] = c.doFinal(ciphertext);
System.out.println("Bob got the string " + new String(plaintext));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
KeyAgreementDemo test = new KeyAgreementDemo();
new Thread(test).start(); // Starts Alice
new Thread(test).start(); // Starts Bob
}
}
以上代码参考了Java Cryptography Extension (JCE) Reference Guide(JDK5.0)中Appendix F的例子。
3. 通过数字信封使用RSA算法协商密钥
数字信封的原理就是利用通讯对方的公钥加密目标密钥(session key,对称密钥),使用目标密钥对报文进行加密,然后将密钥密文与报文密文一起发送给接收方。接收方首先使用自己的私钥对密钥报文进行解密,这样就得到了协商后的密钥,再使用解密后的密钥解密报文,这样就得到了业务数据。过程图示如下:
数字信封的原理
代码示例如下,密钥协商双方由两个线程模拟:
/*
* @(#)DigitalEnvelopeDemo.java 1.0 2012-6-14
*
* Copyright 2010 Richard Chen(utopia_rabbi@sse.buaa.edu.cn) All Rights Reserved.
* PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package charpter.security.keyagreement;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import charpter.security.key.KeyGeneratorDemo;
/**
* 演示使用Digital envelope技术进行密钥交换.
*
* 服务器端与客户端分别由两个独立的线程模拟, 双方指间的通讯由共享内存实现. * * @author Rich, 2012-6-14. * @version 1.0 * @since 1.0 */ public final class DigitalEnvelopeDemo { /** * @param args */ public static void main(String[] args) { KeyPair pair = generatorKeyPair(); Thread client = new Client(pair); Thread server = new Server(pair.getPublic()); server.start(); client.start(); } /** * 生成RSA算法的公私密钥对. * * @return 生成RSA算法的公私密钥对. */ public static final KeyPair generatorKeyPair() { KeyPairGenerator keyGen = null; try { keyGen = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } SecureRandom random = null; try { random = SecureRandom.getInstance("SHA1PRNG"); } catch (Exception e) { throw new RuntimeException(e); } random.setSeed(53); keyGen.initialize(1024, random); KeyPair pair = keyGen.generateKeyPair(); return pair; } /** * 模拟密钥交换的服务器端, 服务器端与客户端通过共享内存来交换Digital Envelope. * * @author Rich, 2012-6-14. * @version 1.0 * @since 1.0 */ static class Server extends Thread { /** * 实际中有可能是客户端在请求服务器端时上送了自己的公钥, 也有可能是在注册 * 时就在服务器端登记了公钥. * * @param clientPublicKey 客户端的公钥. */ public Server(PublicKey clientPublicKey) { this.clientPublicKey = clientPublicKey; } /* (non-Javadoc) * @see java.lang.Thread#run() */ @Override public void run() { try { String msg = "Legend of AK47"; Key sessionKey = KeyGeneratorDemo.generatePlainDES(); Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, sessionKey); byte[] p = msg.getBytes("UTF-8"); byte[] msgCipher = cipher.doFinal(p); cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, clientPublicKey); byte[] keyCipher = cipher.doFinal(sessionKey.getEncoded()); Mapresult = new HashMap(); result.put("msg", msgCipher); result.put("key", keyCipher); CHANNEL.offer(result); } catch (KeyException e) { // TODO Exception handling... } } /** 客户端的公钥. */ private final PublicKey clientPublicKey; } /** * 模拟密钥交换的客户端, 服务器端与客户端通过共享内存来交换Digital Envelope. * * @author Rich, 2012-6-14. * @version 1.0 * @since 1.0 */ static class Client extends Thread { /** * 密钥对应该在客户端内部产生, 然后客户端在请求服务器端时上送了自己的公钥, 也有可能是在注册时就在服务器端登记了公钥. * * @param keyPair 客户端的公私密钥对. */ public Client(KeyPair keyPair) { this.keyPair = keyPair; } /* * (non-Javadoc) * * @see java.lang.Thread#run() */ @Override public void run() { try { Mapreceived = CHANNEL.take(); byte[] msgCipher = received.get("msg"); byte[] keyCipher = received.get("key"); PrivateKey privateKey = keyPair.getPrivate(); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] encoded = cipher.doFinal(keyCipher); KeySpec keySpec = new DESKeySpec(encoded); SecretKeyFactory fac = SecretKeyFactory.getInstance("DES"); Key key = fac.generateSecret(keySpec); cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] msg = cipher.doFinal(msgCipher); String plainText = new String(msg, "UTF-8"); System.out.println(plainText); } catch (Exception e) { // TODO Exception handling... } } /** 客户端的公私密钥对. */ private final KeyPair keyPair; } /** Client端与Server端交换数据的队列, 模拟两者之间通讯的通道, 现实中两者可能是通过Socket通讯的. */ private static final BlockingQueue> CHANNEL = new LinkedBlockingQueue>(1); }
KeyAgreement的DH与数字信封的RSA比较:
——————————————————————————————–
a. DH仅限于交换共享密钥,而无法对交换双方的身份进行认证,易受中间人攻击
b. RSA可以用于交换共享密钥也可以用于身份认证
c. 建议:在双方都有数字证书时,使用RSA,一方或两方都没有数字证书则使用Diffie-Hellman,SSL3.0就是采用的此策略
五. 总结
JCE中最常用和最核心的功能就是加解密,此功能由Cipher组件提供,在使用Cipher前需对加密算法及参数先做出选择:
1. 算法选择
对称算法一般速度较快,非对称算法速度较慢;对称算法的密钥管理比较困难,非对称算法密钥管理简单;非对称算法一般用于认证和加密会话密钥,通讯双方大部分也就是在开启会话时使用一次,对称算法一般用来加密双方之间的报文/交换的数据,使用频度较高。
2. 块/流模式选择
块(Block)模式加密以块为基本单位,适用于明文长度已知的情形;流(Stream)模式以bit或byte为加解密单位, 适用于明文长度未知、内容较大的情形,如加密一个套接字管道或文件读写流等,一般仅适用于硬件实现。块模式下不同算法的块大小可能不一样,一般都是2的次方数,大部分长度为64bits,整个明文长度不是块长度整倍数时,需在最后一个Block进行补长(Padding)
3. 反馈模式选择
使用块算法加密,如果明文有大量重复的内容,则对块加密后得到的密文也会存在大量的重复,这对密文分析、破解提供了极大的便利,为消除这方面的威胁,有个思路就是对不同块密文再进行运算,这样就极大去除了块密文与块明文几间的特征关联,这种做法称为块反馈模式。常见的反馈模式有:ECB、CBC、CFB、OFB等。对于第1个block,因没有其它块密文可供运算,有的模式引入了初始矢量(Initialization Vector,IV,由用户指定)作为第1个block内容,这样就进一步解决了第1个block密文的脆弱性。注意:尽量不要使用ECB模式。
4. 补长方案选择
下面是一些常见的补长(Padding)方案,以DES算法加密明文for为例,因for不足8bytes,所以需补长5bytes(for ?? ?? ?? ?? ??),则这5bytes可能选择(16进制):
——————————————————————————————–
i. 所有Padding以长度为值:66 6F 72 05 05 05 05 05
ii. Padding以0×80开始后面全部为0×00:66 6F 72 80 00 00 00 00
iii. 最后一个字节为Padding长度, 其它为0×00:66 6f 72 00 00 00 00 05
iv. 全部Padding为0×00:66 6f 72 00 00 00 00 00
v. 全部Padding为0×20(空格):66 6f 72 20 20 20 20 20
JCE中支持的补长方案包括:NoPadding、PKCS5Padding、ISO10126Padding、OAEPWithAndPadding和SSL3Padding,NoPadding即不补长,其中最常用的就是PKCS5Padding和ISO10126Padding。
PKCS5Padding,具体规范请参考RSA实验室的文档:PKCS #5 Password-Based Encryption Standard,Version 1.5。简单的说PKCS5Padding就2个规则:
——————————————————————————————–
i. 补长的内容为待补长字节数
ii. 补长的字节数为:8 – 明文长度 % 8,即补长长度在1至8bytes之间
如前述的明文for将补长为:66 6F 72 05 05 05 05 05
ISO10126Padding,具体规范请参考ISO 10126。简单的说ISO10126Padding就是补长的长度作为补长内容的最后一个byte,之前的补长内容为随机数。如前述的明文for可能补长为:66 6F 72 2A 75 EF F8 05
7. 密钥的选择
密钥可以使用KeyGenerator/KeyPairGenerator生成,也可以由外部导入,还可以有密钥参数构造KeySpec再转换为Key。
6. 密钥长度选择
对于对称加密算法,128bits的密钥足够安全,条件许可请选择256bits,注意密钥长度大于128bits需单独下载并安装jurisdiction policy files;对于非对称加密算法,1024bits的密钥足够安全。
最后,如选用基于口令的算法或在用户输入密码时,请避免使用String来引用,使用char[],用完立刻置空char[],避免内存攻击,如heap dump分析等。
参考链接:http://www.ithao123.cn/content-10346659.html
Java安全 – JCE Blowfish算法报错的更多相关文章
- hive算法报错..
hive普通语句查询报错.. 查到以下设定项,,附加在语句前执行成功.. 但是有可能没有真正的执行.. 试到最后使用标红的三行附加在语法前执行成功 set hive.execution.engine= ...
- Android webview js 调用java方法报错"Uncaught TypeError: Object [object Object] has no method xx
webview开发,在Android4.4下js调用java方法报错"Uncaught TypeError: Object [object Object] has no method,同样的 ...
- 项目实体类使用@Data注解,但是项目业务类中使用getA(),setA()方法报错,eclipse中配置lombok
@Data注解来源与Lombok,可以减少代码中大量的set get方法,大量减少冗余代码,但是今天部署项目时候,发现实体类使用@Data注解,但是项目业务类中使用getA(),setA()方法报错. ...
- Java使用dom4j读取xml时报错:org.dom4j.DocumentException: Error on line 2 of document : Invalid byte 2 of 2-byte UTF-8 sequence. Nested exception: Invalid byte 2 of 2-byte UTF-8 sequence
1.Java使用dom4j读取xml时报错: org.dom4j.DocumentException: Error on line 2 of document : Invalid byte 2 of ...
- eclipse中运行 main 方法报错,找不到类
eclipse (maven 项目)中运行 main 方法报错,找不到类 ** 发现:在 eclipse中的 "Marker" 控制面板中 ,发现问题所在 只要删除 maven 仓 ...
- webstorm中es6语法报错,.vue文件中es6语法报错
1.webstorm中es6语法报错,解决方法: 打开 Settings => Languages & Frameworks => Javascript把 Javascript L ...
- appium+python自动化64-使用Uiautomator2执行driver.keyevent()方法报错解决
前言 未加'automationName': 'Uiautomator2'参数使用Uiautomator可以正常使用driver.keyevent()方法,使用Uiautomator2时driver. ...
- java面试题最容易犯错
1. static 和 final 的用法 static 的作用从三个方面来谈,分别是静态变量.静态方法.静态类. 静态变量:声明为 static 的静态变量实质上就是全局变量,当声明一个对象时,并不 ...
- 字符串replaceAll()方法报错:java.util.regex.PatternSyntaxException:Unclosed group near index...
Unclosed group near index错误 之前自己写的一个模块在项目上线后最近频频出现tomcat崩掉的情况,从log看出现如下的报错信息: java.util.regex.Patter ...
随机推荐
- 分布式锁-基于ZK和Redis实现
一.基于zookeeper实现分布式锁 1.1 Zookeeper的常用接口 package register; import java.util.List; import java.util.con ...
- Linux系统中DHCP的配置
DHCP为动态主机配置协议,负责IP地址的动态分配(当一个主机的IP为自动,则不需要自己写IP,他会在DHCP服务器的范围内自动获取) 在真机或虚拟机下配置DHCP服务时,需要先下载dhcp软件,使用 ...
- restify构建REST服务(转)
restify构建REST服务 从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Java ...
- c++多线程编程:实现标准库accumulate函数的并行计算版本
今天使用c++实现了标准库头文件<numeric>中的accumulate函数的并行计算版本,代码如下,注释写的比较详细,仅对其中几点进行描述: ①该实现假定不发生任何异常,故没有对可能产 ...
- three.js入门——先跑个旋转的正方体
WebGl中文网看了几篇教程,又百度了几篇文章,顿时感觉手痒,打开编辑器,写个demo玩玩. demo是写在vue项目中的,所以首先: npm install three --save; npm in ...
- 利用层序遍历(含空节点)和中序遍历重建二叉树 python
给定一颗二叉树的层序遍历(不含None的形式)和中序遍历序列,利用两个序列完成对二叉树的重建. 还是通过一个例子来说明整个过程,下图所示的二叉树,层序遍历结果为[a,b,c,d,e],中序遍历结果为[ ...
- java android 读写三菱PLC 使用TCP/IP 协议
本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...
- Uncaught TypeError: jQuery.i18n.browserLang is not a function
/********************************************************************* * Uncaught TypeError: jQuery. ...
- HDU2037 今年暑假不AC
解题思路:贪心问题,关键突破口是,先将节目的结束时间 从小到大排个序,然后依次判断后面一个节目的开始时间 是否大于或等于前一个符合条件的节目的结束时间.见代码: #include<cstdio& ...
- Java [Leetcode 384]Shuffle an Array
题目描述: Shuffle a set of numbers without duplicates. Example: // Init an array with set 1, 2, and 3. i ...