开发一个JCE的Provider

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));

 结果如下:


开发一个JCE的Provider_第1张图片

 

你可能感兴趣的:(java,Provider,JCE,PKI,cipher)