stoutT 2008-05-14
项目中需要与delphi交换。为了增强安全性这两天学习了下几种算法今晚把这两天的心得及代码贴上来交流下:
我们的想法是这样的:
delphi生成密匙文件。java使用密匙文件加密或解密。delphi也使用同一个密匙文件加密或解密。我做了两种加密方式的实现rsa跟des。我做完后发现两个方式使用java生成的密匙文件文件加密解密都是没问题的,但使用delphi生成的密匙文件就不能加密或解密。下面我把我的代码贴上来请指点下。
一。加密接口
import java.io.IOException; public interface CodeBean { /** * 编码 * @return */ public byte[] encode(byte [] cipherText)throws Exception; /** * 解码 * @return */ public byte[] decode(byte [] cipherText)throws Exception; }
二。Rsa加密实现
public class RsaEncoder implements InitializingBean, CodeBean { private final String KEY_ENCODE = "ENCODE";// 编码 private final String KEY_DECODE = "DECODE";// 解码 private String chartSet = "UTF-8"; private String publickey;// ENCODE/DECODE private String privatekey;// ENCODE/DECODE private String publicKeyPath = null; private String privatekeypath = null; public void afterPropertiesSet() throws Exception { if (!StringUtils.hasText(this.getPrivatekey()) && !StringUtils.hasText(this.getPublickey())) throw new BeanInitializationException("请设置publickey或privatekey值"); if (StringUtils.hasText(this.getPublickey())) Assert.notNull(publicKeyPath); if (StringUtils.hasText(this.getPrivatekey())) Assert.notNull(privatekeypath); } /** * 解码 * * @throws IOException * @throws NoSuchAlgorithmException * @throws BadPaddingException * @throws IllegalBlockSizeException * @throws NoSuchPaddingException * @throws InvalidKeyException * @throws InvalidKeySpecException */ public byte[] decode(byte [] cipherText) throws Exception { Cipher cipher = null; if (KEY_DECODE.equals(this.getPublickey())) { PublicKey pubKey = (PublicKey)loadKey(this.getPublicKeyPath(),1); cipher = Cipher.getInstance("RSA",new BouncyCastleProvider()); cipher.init(Cipher.DECRYPT_MODE, pubKey); } else { PrivateKey privKey = (PrivateKey)loadKey(this.getPrivatekeypath(),0); cipher = Cipher.getInstance("RSA",new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, privKey); } byte[] newPlainText = cipher.doFinal(cipherText); return newPlainText; } /** * 加密 * @param cipherText * @return * @throws IOException */ public byte[] encode(byte [] cipherText) throws Exception { Cipher cipher = null; KeyFactory keyFactory = KeyFactory.getInstance("RSA",new BouncyCastleProvider()); if (KEY_ENCODE.equals(this.getPublickey())) { PublicKey pubKey = (PublicKey)loadKey(this.getPublicKeyPath(),1); //cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher = Cipher.getInstance("RSA",new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, pubKey); } else { PrivateKey privKey = (PrivateKey)loadKey(this.getPrivatekeypath(),0); //cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher = Cipher.getInstance("RSA",new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, privKey); } byte[] newPlainText = cipher.doFinal(cipherText); return newPlainText; } /** * @param filename * @param type: * 1-public 0-private * @return * @throws ConfigurationException * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public Key loadKey(String filename, int type) throws Exception { System.out.println("filename:" + filename); PropertiesConfiguration config = new PropertiesConfiguration(filename); KeyFactory keyFactory = KeyFactory.getInstance("RSA", new BouncyCastleProvider()); File file = new File(filename); if (filename == null || filename.equals("")) { throw new NullPointerException("无效的文件路径"); } long len = file.length(); byte[] bytes = new byte[(int) len]; BufferedInputStream bufferedInputStream = new BufferedInputStream( new FileInputStream(file)); int r = bufferedInputStream.read(bytes); if (r != len) throw new IOException("读取文件不正确"); bufferedInputStream.close(); if (type == 0) { // privateKey PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(bytes); PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8); return privateKey; } else { // publicKey X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bytes); PublicKey publicKey = keyFactory.generatePublic(bobPubKeySpec); return publicKey; } } public String getPrivatekeypath() { return privatekeypath; } public void setPrivatekeypath(String privatekeypath) { this.privatekeypath = privatekeypath; } public String getPublicKeyPath() { return publicKeyPath; } public void setPublicKeyPath(String publicKeyPath) { this.publicKeyPath = publicKeyPath; } public String getPrivatekey() { return privatekey; } public void setPrivatekey(String privatekey) { this.privatekey = privatekey.toUpperCase(); } public String getPublickey() { return publickey; } public void setPublickey(String publickey) { this.publickey = publickey.toUpperCase(); } public String getChartSet() { return chartSet; } public void setChartSet(String chartSet) { this.chartSet = chartSet; } public String getKEY_ENCODE() { return KEY_ENCODE; } public String getKEY_DECODE() { return KEY_DECODE; } }
Rsa加密解密的测试
public static void main(String[]arg){ byte[] byt = null; try { String encryptText = "ouxueying"; System.out.println("第一种方式.........................."); RsaEncoder rsaEncoder1 = new RsaEncoder(); rsaEncoder1.setChartSet("utf-8"); rsaEncoder1.setPrivatekey("ENCODE");//DECODE rsaEncoder1.setPrivatekeypath("F:\\PrivateKey.key"); rsaEncoder1.setPublickey("DECODE");//ENCODE rsaEncoder1.setPublicKeyPath("F:\\PublicKey.key"); System.out.println("加密:..........." ); byte [] byt1 = rsaEncoder1.encode(encryptText.getBytes()); //System.out.println("加密结果:" + toHexString(byt)); System.out.println("解密:..........." ); byte[] b1 = rsaEncoder1.decode(byt1); System.out.println("解密结果: " + new String(b1)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
三。des加密解密的实现
public class DesEncoder implements CodeBean { Cipher ecipher; Cipher dcipher; //密匙路径 private String keyPath = null; public static void main(String[] arg) { String str = "123"; try { DesEncoder des = new DesEncoder(); des.setKeyPath("F:\\desKey.key"); //SecretKey se = des.generateKey(); //des.saveKey(des.getKeyPath(),se); //System.out.println("MD5 KEY完成"); des.init(des.loadKey(des.getKeyPath())); byte[] utf8 = str.getBytes(); byte[] enc = des.encode(utf8); String s = Converts.bytesToHexString(enc); System.out.println("加密结果:" + s); //byte[] enc = "02BB6C".getBytes(); byte[] utf = des.decode(enc); System.out.println("结果:" + new String(utf,"UTF-8")); } catch (Exception ex) { ex.printStackTrace(); } } /** * 初始化加密器 * @param key */ public void init(SecretKey key) { try { ecipher = Cipher.getInstance("DES"); dcipher = Cipher.getInstance("DES"); ecipher.init(Cipher.ENCRYPT_MODE, key); dcipher.init(Cipher.DECRYPT_MODE, key); } catch (javax.crypto.NoSuchPaddingException e) { } catch (java.security.NoSuchAlgorithmException e) { } catch (java.security.InvalidKeyException e) { } } /** * 生成KEY * @return * @throws Exception */ public SecretKey generateKey() throws Exception { SecretKey key = KeyGenerator.getInstance("DES").generateKey(); this.saveKey(this.getKeyPath(), key); return key; } /** * 解码 */ public byte[] decode(byte[] dec) throws Exception { byte[] utf8 = dcipher.doFinal(dec); return utf8; } /** * 编码 */ public byte[] encode(byte[] utf8) throws Exception { byte[] enc = ecipher.doFinal(utf8); return enc; } /** * 从密匙文件生成KEY * @param filename * @return * @throws Exception */ public SecretKey loadKey(String filename) throws Exception { System.out.println("filename:" + filename); //实例化文件对象 File file = new File(filename); if (filename == null || filename.equals("")) { throw new NullPointerException("无效的文件路径"); } long len = file.length(); byte[] bytes = new byte[(int) len]; BufferedInputStream bufferedInputStream = new BufferedInputStream( new FileInputStream(file)); //读取密匙文件 int r = bufferedInputStream.read(bytes); if (r != len) throw new IOException("读取文件不正确"); bufferedInputStream.close(); byte rawKeyData[] = bytes; // 从原始密匙数据创建一个DESKeySpec对象 DESKeySpec dks = new DESKeySpec(rawKeyData); // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成 // 一个SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey key = keyFactory.generateSecret(dks); return key; } /** * 将密匙存到密匙文件中 * @param filename * @param key * @throws Exception */ public void saveKey(String filename, Key key) throws Exception { System.out.println("保存filename:" + filename); File file = new File(filename); BufferedOutputStream pubout = new BufferedOutputStream(new FileOutputStream(filename)); byte[] keyt = key.getEncoded(); java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" ); md.update( keyt ); byte tmp[] = md.digest(); // System.out.println(Converts.); pubout.write(tmp); pubout.close(); } public String getKeyPath() { return keyPath; } public void setKeyPath(String keyPath) { this.keyPath = keyPath; } }
四.在使用delphi密匙时rsa des都会报错:
java.security.spec.InvalidKeySpecException: java.lang.IllegalArgumentException: unknown object in factory at org.bouncycastle.jce.provider.JDKKeyFactory$RSA.engineGeneratePublic(Unknown Source) at java.security.KeyFactory.generatePublic(KeyFactory.java:278) at com.hitech.cpp.components.encoding.RsaEncoder.loadKey(Unknown Source) at com.hitech.cpp.components.encoding.RsaEncoder.decode(Unknown Source) at com.hitech.cpp.components.encoding.RsaEncoderTest.main(Unknown Source)