1、开发环境ubuntu+eclipse+openJDK
本来想在xp下开发,但是JDK1.6中有层层限制:JCA对外出口但是JCE对外不出口,当你实现后调用Cipher会报如下错误:
Exception in thread "main" java.lang.SecurityException: JCE cannot authenticate the provider SecureProvider
at javax.crypto.Cipher.getInstance(DashoA13*..)
at com.ligson.test.SimpleTest.main(SimpleTest.java:19)
Caused by: java.util.jar.JarException: Cannot parse file:/E:/code/itrusca/MyProvider/target/classes/
at javax.crypto.SunJCE_c.a(DashoA13*..)
at javax.crypto.SunJCE_b.b(DashoA13*..)
at javax.crypto.SunJCE_b.a(DashoA13*..)
... 2 more
意思是让你去用自己产生的CSR提交到SUN的CA中心(IBM旗下也有)产生一张证书,进行代码签名(据我找到的信息,他一般是不会向你颁发证书的,也许你会说BouncyCastle就有自己的Provider,但是人家不是中国的)
2、Provider的实现
package com.ligson.provider;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.AuthProvider;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.SecurityPermission;
import java.util.jar.JarException;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import com.ligson.jce.impl.SM3MessageDigest;
public final class SecureProvider extends AuthProvider {
private static String name = "SecureProvider";
private static String info = "this is a test provider for sm2/sm3";
private static double version = 1.0d;
public SecureProvider() {
super(name, version, info);
// this.putService(s);
//授权
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
//放入自己的基础实现类
//格式:类型.算法
put("Cipher.SM2", "com.ligson.jce.impl.SM2Cipher");
put("MessageDigest.SM3", SM3MessageDigest.class.getName());
put("Cipher.Simple", "com.ligson.provider.SimpleCipher");
put("KeyGenerator.Simple",
"com.ligson.provider.SimpleKeyGenerator");
return null;
}
});
}
private static URL getClassURL(final Class<?> clazz) {
return AccessController.doPrivileged(new PrivilegedAction<URL>() {
public URL run() {
CodeSource cs = clazz.getProtectionDomain().getCodeSource();
return cs.getLocation();
}
});
}
/**
*
*/
private static final long serialVersionUID = 1L;
public String getName() {
return name;
}
public String getInfo() {
return info;
}
public double getVersion() {
return version;
}
public static interface Tst {
}
@Override
public void login(Subject subject, CallbackHandler handler)
throws LoginException {
SecurityManager sm = System.getSecurityManager();
sm.checkPermission(new SecurityPermission("authProvider."
+ this.getName()));
}
@Override
public void logout() throws LoginException {
// TODO Auto-generated method stub
}
@Override
public void setCallbackHandler(CallbackHandler handler) {
// TODO Auto-generated method stub
};
}
3、SimpleCipher的实现,原理很简单,就是把输入的byte[]的每一个byte元素加上一个随机数,解密的时候再减去
package com.ligson.provider;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherSpi;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
public class SimpleCipher extends CipherSpi {
private int mode;
private Key key;
private byte[] in;
@Override
protected byte[] engineDoFinal(byte[] arg0, int arg1, int arg2)
throws IllegalBlockSizeException, BadPaddingException {
return implDoFinal();
}
@Override
protected int engineDoFinal(byte[] arg0, int arg1, int arg2, byte[] arg3,
int arg4) throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
return 0;
}
@Override
protected int engineGetBlockSize() {
return 0;
}
@Override
protected byte[] engineGetIV() {
return null;
}
@Override
protected int engineGetOutputSize(int arg0) {
return 0;
}
@Override
protected AlgorithmParameters engineGetParameters() {
return null;
}
@Override
protected void engineInit(int arg0, Key arg1, SecureRandom arg2)
throws InvalidKeyException {
implInit(arg0, arg1);
}
@Override
protected void engineInit(int arg0, Key arg1, AlgorithmParameterSpec arg2,
SecureRandom arg3) throws InvalidKeyException,
InvalidAlgorithmParameterException {
implInit(arg0, arg1);
}
@Override
protected void engineInit(int arg0, Key arg1, AlgorithmParameters arg2,
SecureRandom arg3) throws InvalidKeyException,
InvalidAlgorithmParameterException {
implInit(arg0, arg1);
}
@Override
protected void engineSetMode(String arg0) throws NoSuchAlgorithmException {
}
@Override
protected void engineSetPadding(String arg0) throws NoSuchPaddingException {
}
@Override
protected byte[] engineUpdate(byte[] arg0, int arg1, int arg2) {
return implUpdate(arg0, arg1, arg2);
}
@Override
protected int engineUpdate(byte[] arg0, int arg1, int arg2, byte[] arg3,
int arg4) throws ShortBufferException {
return 0;
}
private void implInit(int mode, Key key) {
this.mode = mode;
if (key instanceof SimpleKey) {
this.key = key;
} else {
throw new RuntimeException("key invalid!");
}
}
private byte[] implUpdate(byte[] in, int offset, int len) {
this.in = in;
return in;
}
private byte[] implDoFinal() {
SimpleKey simpleKey = (SimpleKey) key;
if (mode == Cipher.ENCRYPT_MODE) {
for (int i = 0; i < in.length; i++) {
in[i] = (byte) (in[i] + simpleKey.offset);
}
} else if (mode == Cipher.DECRYPT_MODE) {
for (int i = 0; i < in.length; i++) {
in[i] = (byte) (in[i] - simpleKey.offset);
}
} else {
throw new RuntimeException("mode must be encrypt or decrypt!");
}
return in;
}
public void init(int mode, Key key) {
implInit(mode, key);
}
public void update(byte[] in, int offset, int len) {
implUpdate(in, offset, len);
}
public byte[] doFinal() {
return implDoFinal();
}
}
4、SimpleKey(只是一个简单的对称密钥)的实现,里面只保存随机的偏移量、长度等
package com.ligson.provider;
import java.security.SecureRandom;
import javax.crypto.SecretKey;
public class SimpleKey implements SecretKey {
protected int len;
protected SecureRandom random;
protected int offset;
SimpleKey(SecureRandom random, int keySize,int offset) {
this.len = keySize;
this.random = random;
this.offset = offset;
}
@Override
public String getAlgorithm() {
return "Simple";
}
@Override
public String getFormat() {
return "";
}
@Override
public byte[] getEncoded() {
byte[] b = new byte[len];
random.nextBytes(b);
return b;
}
}
5、SimpleKeyGenerator的实现
package com.ligson.provider;
import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
public class SimpleKeyGenerator extends KeyGeneratorSpi {
private SecureRandom random = new SecureRandom();
private int keySize = 128;
private int offset = 3;
@Override
protected SecretKey engineGenerateKey() {
offset = random.nextInt();
return new SimpleKey(random,keySize,offset);
}
@Override
protected void engineInit(SecureRandom secureRandom) {
this.random = secureRandom;
}
@Override
protected void engineInit(AlgorithmParameterSpec arg0, SecureRandom arg1)
throws InvalidAlgorithmParameterException {
throw new InvalidAlgorithmParameterException("no support operation");
}
@Override
protected void engineInit(int keySize, SecureRandom secureRandom) {
this.keySize = keySize;
this.random = secureRandom;
}
}
6、Provider的测试程序
SecureProvider provider = new SecureProvider();
Security.addProvider(provider);
KeyGenerator generator = KeyGenerator.getInstance("Simple",provider);
System.out.println(generator);
generator.init(512);
SecretKey secretKey = generator.generateKey();
System.out.println(Arrays.toString(secretKey.getEncoded()));
byte[] plain = "password".getBytes();
System.out.println(Arrays.toString(plain));
Cipher cipher = Cipher.getInstance("Simple");
cipher.init(Cipher.ENCRYPT_MODE,secretKey);
cipher.update(plain);
byte[] result = cipher.doFinal();
System.out.println(Arrays.toString(result));
cipher.init(Cipher.DECRYPT_MODE,secretKey);
cipher.update(result);
byte[] result2 = cipher.doFinal();
System.out.println(Arrays.toString(result2));
System.out.println(Arrays.equals(result2,plain));
结果如下:
版权声明:本文为tianlang519241原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。