RSA生成密文转HEX的String

JAVA RSA 生成公钥私钥以及对密文的编码转换
整体代码:

package com.qingyu.pay.mobile.vo;
 
 
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
 
import javax.crypto.Cipher;

import com.mysql.jdbc.util.Base64Decoder;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
 
public class CreateSecretKey {
 public static final String KEY_ALGORITHM = "RSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
 public static final String SIGNATURE_ALGORITHM="MD5withRSA";

 private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', 
         '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
private static final int MAX_ENCRYPT_BLOCK = 117;

    private static final int MAX_DECRYPT_BLOCK = 128;
    //获得公钥字符串
    public static String getPublicKeyStr(Map keyMap) throws Exception {
        //获得map中的公钥对象 转为key对象
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        //编码返回字符串
        return encryptBASE64(key.getEncoded());
    }
 
 
    //获得私钥字符串
    public static String getPrivateKeyStr(Map keyMap) throws Exception {
        //获得map中的私钥对象 转为key对象
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        //编码返回字符串
        return encryptBASE64(key.getEncoded());
    }
    
    //获取公钥
    public static PublicKey getPublicKey(String key) throws Exception {  
        byte[] keyBytes;  
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);  
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
        PublicKey publicKey = keyFactory.generatePublic(keySpec);  
        return publicKey;  
    }  
    
    //获取私钥
    public static PrivateKey getPrivateKey(String key) throws Exception {  
        byte[] keyBytes;  
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);  
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);  
        return privateKey;  
    }
    
    //解码返回byte
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }
 
 
    //编码返回字符串
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }
    
    //***************************签名和验证*******************************  
    public static byte[] sign(byte[] data,String privateKeyStr) throws Exception{  
      PrivateKey priK = getPrivateKey(privateKeyStr);  
      Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);       
      sig.initSign(priK);  
      sig.update(data);  
      return sig.sign();  
    }  
    
    public static boolean verify(byte[] data,byte[] sign,String publicKeyStr) throws Exception{  
      PublicKey pubK = getPublicKey(publicKeyStr);  
      Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);  
      sig.initVerify(pubK);  
      sig.update(data);  
      return sig.verify(sign);  
    }  
    
  //************************加密解密**************************  
    public static byte[] encrypt(byte[] plainText,String publicKeyStr)throws Exception{  
        PublicKey publicKey = getPublicKey(publicKeyStr);  
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
        int inputLen = plainText.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        int i = 0;
        byte[] cache;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(plainText, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptText = out.toByteArray();
        out.close();  
        return encryptText;  
    }  
      
    public static byte[] decrypt(byte[] encryptText,String privateKeyStr)throws Exception{  
        PrivateKey privateKey = getPrivateKey(privateKeyStr);  
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);  
        int inputLen = encryptText.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptText, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptText, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] plainText = out.toByteArray();
        out.close();  
        return plainText;  
    }  
 
 
    public static void main(String[] args) {
        Map keyMap;
        byte[] cipherText;
        String input = "再仔细核对上述登录流程, 我们发现服务器判断用户是否登录, 完全依赖于sessionId, 一旦其被截获, 黑客就能够模拟出用户的请求。于是我们需要引入token的概念: 用户登录成功后, 服务器不但为其分配了sessionId, 还分配了token, token是维持登录状态的关键秘密数据。在服务器向客户端发送的token数据,也需要加密。于是一次登录的细节再次扩展";
        try {
            keyMap = initKey();
            String publicKey = getPublicKeyStr(keyMap);
            System.out.println("公钥------------------");
            System.out.println(publicKey);
            String privateKey = getPrivateKeyStr(keyMap);
            System.out.println("私钥------------------");
            System.out.println(privateKey);
            
            System.out.println("测试可行性-------------------");
            System.out.println("明文======="+input);
            
            cipherText = encrypt(input.getBytes(),publicKey); 
            //加密后的东西 
                char[] buf = new char[cipherText.length * 2];
                int index = 0;
                for(byte b : cipherText) { // 利用位运算进行转换,可以看作方法一的变种
                    buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
                    buf[index++] = HEX_CHAR[b & 0xf];
                }
            System.out.println("密文======="+new String(buf));
            //开始解密 
            byte[] bytes = new byte[new String(buf).length() / 2];
            for(int i = 0; i < new String(buf).length() / 2; i++) {
                String subStr = new String(buf).substring(i * 2, i * 2 + 2);
                bytes[i] = (byte) Integer.parseInt(subStr, 16);
            }
 
            byte[] plainText = decrypt(bytes,privateKey); 
            System.out.println("解密后明文===== " + new String(plainText));

            
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static Map initKey() throws Exception {  
    	  KeyPairGenerator keyPairGen = KeyPairGenerator  
    	    .getInstance(KEY_ALGORITHM);  
    	  keyPairGen.initialize(1024);  
    	  KeyPair keyPair = keyPairGen.generateKeyPair();  
    	  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
    	  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  
    	  Map keyMap = new HashMap(2);  
    	  keyMap.put(PUBLIC_KEY, publicKey);  
    	  keyMap.put(PRIVATE_KEY, privateKey);  
    	  return keyMap;  
    	 }  
}

代码简介:

KeyPairGenerator keyPairGen = KeyPairGenerator  
    	    .getInstance(KEY_ALGORITHM);

KeyPairGenerator 类用于生成公钥和私钥对。密钥对生成器是使用 getInstance 工厂方法(返回一个给定类的实例的静态方法)构造的。

特定算法的密钥对生成器可以创建能够与此算法一起使用的公钥/私钥对。它还可以将特定于算法的参数与每个生成的密钥关联。

有两种生成密钥对的方式:与算法无关的方式和特定于算法的方式。两种方式的唯一区别在于对象的初始化:

与算法无关的初始化
所有的密钥对生成器遵循密钥大小和随机源的概念。对于不同的算法,密钥大小的解释也不相同(例如,对于 DSA 算法,密钥大小对应于模的长度)。此 KeyPairGenerator 类有一个 initialize 方法,该方法带有两个通用的共享类型的参数。还有一个只带有 keysize 参数的方法,它使用以最高优先级安装的提供者的 SecureRandom 实现作为随机源。(如果任何安装的提供者都不提供 SecureRandom 的实现,则使用系统提供的随机源。)

因为调用上述与算法无关的 initialize 方法时没有指定其他参数,所以由提供者决定如何处理与每个密钥关联的特定于算法的参数(如果有)。

如果算法为 DSA 算法,密钥大小(模大小)为 512、768 或 1024,那么 Sun 提供者对 p、q 和 g 参数使用一组预计算值。如果模大小不是上述值之一,则 Sun 提供者创建一个新的参数集合。其他提供者可能具有供更多模大小(不仅仅是上文提及的那三个)使用的预计算参数集合。其他提供者也可能没有任何预计算参数列表,而总是创建新的参数集合。

特定于算法的初始化
对于特定于算法的参数集合已存在的情况(例如,DSA 中所谓的公用参数),有两个 initialize 方法具有 AlgorithmParameterSpec 参数。其中一个方法还有一个 SecureRandom 参数,而另一个方法使用以最高优先级安装的提供者的 SecureRandom 实现作为随机源。(如果任何安装的提供者都不提供 SecureRandom 的实现,则使用系统提供的随机源。)

每个提供者都必须提供(并记录)默认的初始化,以防客户端没有显式初始化 KeyPairGenerator(通过调用 initialize 方法)。例如,Sun 提供者使用 1024 位的默认模大小(密钥大小)。

注意,由于历史原因,此类是抽象类,是从 KeyPairGeneratorSpi 扩展的。应用程序开发人员只需注意在此 KeyPairGenerator 类中定义的方法;超类中的所有方法是供加密服务提供者使用的,这些加密服务提供者希望提供自己的密钥对生成器实现
KeyPairGenerator(String algorithm)
为指定的算法创建 KeyPairGenerator 对象。

  keyPairGen.initialize(1024);

initialize(int keysize)
初始化确定密钥大小的密钥对生成器,使用默认的参数集合,并使用以最高优先级安装的提供者的 SecureRandom 实现作为随机源。
一行一行讲解太麻烦了…跳过…感兴趣看JDK文档
JDK1.6中文文档

在加密中有些必要对密文进行传输,Cipher类加密完成后事byte类型不能直接在网络中传输,直接用new String(),转出来的会乱码
类似这种:
�g��׿u�
回转也会出问题。所以需要转成HEX的String类型字符串。

char[] buf = new char[cipherText.length * 2];
                int index = 0;
                for(byte b : cipherText) { 
                    buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
                    buf[index++] = HEX_CHAR[b & 0xf];
                }

这个转16进制就是长度乘以2,不够两位的高位补0。
转过之后类似:
5842c9cfec112da80567ac0898d7bf759c009f52dd3534
接收到密文后在对HEX的String进行转byte

byte[] bytes = new byte[new String(buf).length() / 2];
            for(int i = 0; i < new String(buf).length() / 2; i++) {
                String subStr = new String(buf).substring(i * 2, i * 2 + 2);
                bytes[i] = (byte) Integer.parseInt(subStr, 16);
            }

解密完成之后就是加密之后的byte了 再用RSA解密就行。

你可能感兴趣的:(java,RSA,后台)