当前位置: 安卓之星 -> Java开发 -> java非对称加密RSA工具类代码实现

java非对称加密RSA工具类代码实现

作者:网络 发表于: 2017-01-21 点击: 235 次

先阐述一下原理:

1.欧拉定理

aφ(n) ≡ 1 (mod n)

这个公式的意思是a的φ(n)次方除以 n 余1,欧拉方程φ(n)表示{1,2,3…n}中与n互质关系的整数的个数。互质关系就是两个数除了1以外没有公约数。
什么是互质关系呢?
如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime)。
比如,15和32没有公因子,所以它们是互质关系。这说明,不是质数也可以构成互质关系。

2.模反元素

欧拉函数本身需要一系列复杂推导,本部分仅介绍对认识RSA算法有帮助的部分

任意给定正整数n,计算在小于等于n的正整数之中,有多少个与n构成互质关系?
计算这个值的方法就叫做欧拉函数,以φ(n)表示.
例如,在1到8之中,与8形成互质关系的是1、3、5、7,所以φ(n)=4

在RSA算法中,我们需要明白欧拉函数对以下定理成立

如果n可以分解成两个互质的整数之积,即n=p×q,则有:φ(n)=φ(pq)=φ(p)φ(q);
根据“大数是质数的两个数一定是互质数”可以知道:
一个数如果是质数,则小于它的所有正整数与它都是互质数;
所以如果一个数p是质数,则有:φ(p)=p-1
由上易得,若我们知道一个数n可以分解为两个质数p和q的乘积,则有
φ(n)=(p-1)(q-1)

3.公钥加密和私钥解密

公钥加密公式
me ≡ c (mod n)
也可以写为
c = me mod n
私钥解密公式
cd ≡ m (mod n)
也可以写为
m = cd mod n
看起来可能有些不明白,说明下这几个参数的含义,其中
m: 将加密的明文
c: 加密的密文
n: 模数,两个很大的质数的乘积
e: 公钥指数
d: 私钥指数
(n,e) 是公钥
(n,d) 是私钥
d是e对于φ(n)的模反元素

公钥加密和私钥解密过程

RSA实现的代码:

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
 
import javax.crypto.Cipher;
 
public class RSA {
 
    public static void main(String ...args){
        RSA rsa = RSA.create();
        String pubKey = rsa.getPublicKey();
        String priKey = rsa.getPrivateKey();
        //原文
        StringBuffer res = new StringBuffer();
        for (int i = 0; i < 40; i++) {
            res.append("测试");
        }
        System.out.println("原文对比:"+res.toString());
        System.out.println("------------");
        String enStr = rsa.encodeByPublicKey(res.toString(), pubKey);
        String deStr = rsa.decodeByPrivateKey(enStr, priKey);
        System.out.println("公钥加密:"+enStr);
        System.out.println("私钥解密:"+deStr);
        System.out.println("------------");
        enStr = rsa.encodeByPrivateKey(res.toString(), priKey);
        deStr = rsa.decodeByPublicKey(enStr, pubKey);
        System.out.println("私钥加密:"+enStr);
        System.out.println("公钥解密:"+deStr);
    }
 
    public static final String KEY_ALGORITHM = "RSA";
    public static final String split = " ";//分隔符
    public static final int max = 117;//加密分段长度//不可超过117
 
    private static RSA me;
    private RSA(){}//单例
    public static RSA create(){
        if (me==null) {
            me = new RSA();
        }
        //生成公钥、私钥
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            kpg.initialize(1024);
            KeyPair kp = kpg.generateKeyPair();
            me.publicKey = (RSAPublicKey) kp.getPublic();
            me.privateKey = (RSAPrivateCrtKey) kp.getPrivate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return me;
    }
 
    private RSAPublicKey publicKey;
    private RSAPrivateCrtKey privateKey;
 
    /**获取公钥*/
    public String getPublicKey(){
        return parseByte2HexStr(publicKey.getEncoded());
    }
 
    /**获取私钥*/
    public String getPrivateKey(){
        return parseByte2HexStr(privateKey.getEncoded());
    }
 
    /**加密-公钥*/
    public String encodeByPublicKey(String res,String key){
        byte[] resBytes = res.getBytes();
        byte[] keyBytes = parseHexStr2Byte(key);//先把公钥转为2进制
        StringBuffer result = new StringBuffer();//结果
        //如果超过了100个字节就分段
        if (keyBytes.length<=max) {//不超过直接返回即可
            return encodePub(resBytes, keyBytes);
        }else {
            int size = resBytes.length/max + (resBytes.length%max>0?1:0);
            for (int i = 0; i < size; i++) {
                int len = i==size-1?resBytes.length%max:max;
                byte[] bs = new byte[len];//临时数组
                System.arraycopy(resBytes, i*max, bs, 0, len);
                result.append(encodePub(bs, keyBytes));
                if(i!=size-1)result.append(split);
            }
            return result.toString();
        }
    }
    /**加密-私钥*/
    public String encodeByPrivateKey(String res,String key){
        byte[] resBytes = res.getBytes();
        byte[] keyBytes = parseHexStr2Byte(key);
        StringBuffer result = new StringBuffer();
        //如果超过了100个字节就分段
        if (keyBytes.length<=max) {//不超过直接返回即可
            return encodePri(resBytes, keyBytes);
        }else {
            int size = resBytes.length/max + (resBytes.length%max>0?1:0);
            for (int i = 0; i < size; i++) {
                int len = i==size-1?resBytes.length%max:max;
                byte[] bs = new byte[len];//临时数组
                System.arraycopy(resBytes, i*max, bs, 0, len);
                result.append(encodePri(bs, keyBytes));
                if(i!=size-1)result.append(split);
            }
            return result.toString();
        }
    }
    /**解密-公钥*/
    public String decodeByPublicKey(String res,String key){
        byte[] keyBytes = parseHexStr2Byte(key);
        //先分段
        String[] rs = res.split("\\"+split);
        //分段解密
        if(rs!=null){
            int len = 0;
            //组合byte[]
            byte[] result = new byte[rs.length*max];
            for (int i = 0; i < rs.length; i++) {
                byte[] bs = decodePub(parseHexStr2Byte(rs[i]), keyBytes);
                System.arraycopy(bs, 0, result, i*max, bs.length);
                len+=bs.length;
            }
            byte[] newResult = new byte[len];
            System.arraycopy(result, 0, newResult, 0, len);
            //还原字符串
            return new String(newResult);
        }
        return null;
    }
    /**解密-私钥*/
    public String decodeByPrivateKey(String res,String key){
        byte[] keyBytes = parseHexStr2Byte(key);
        //先分段
        String[] rs = res.split("\\"+split);
        //分段解密
        if(rs!=null){
            int len = 0;
            //组合byte[]
            byte[] result = new byte[rs.length*max];
            for (int i = 0; i < rs.length; i++) {
                byte[] bs = decodePri(parseHexStr2Byte(rs[i]), keyBytes);
                System.arraycopy(bs, 0, result, i*max, bs.length);
                len+=bs.length;
            }
            byte[] newResult = new byte[len];
            System.arraycopy(result, 0, newResult, 0, len);
            //还原字符串
            return new String(newResult);
        }
        return null;
    }
 
    /**将二进制转换成16进制 */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);  
            if (hex.length() == 1) {
                hex = '0' + hex;  
            }
            sb.append(hex.toUpperCase());  
        }
        return sb.toString();  
    }
    /**将16进制转换为二进制*/
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length()/2];
        for (int i = 0;i< hexStr.length()/2; i++) {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
            result[i] = (byte) (high * 16 + low);  
        }
        return result;  
    }
 
    /**加密-公钥-无分段*/
    private String encodePub(byte[] res,byte[] keyBytes){
        X509EncodedKeySpec x5 = new X509EncodedKeySpec(keyBytes);//用2进制的公钥生成x509
        try {
            KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM);
            Key pubKey = kf.generatePublic(x5);//用KeyFactory把x509生成公钥pubKey
            Cipher cp = Cipher.getInstance(kf.getAlgorithm());//生成相应的Cipher
            cp.init(Cipher.ENCRYPT_MODE, pubKey);//给cipher初始化为加密模式,以及传入公钥pubKey
            return parseByte2HexStr(cp.doFinal(res));//以16进制的字符串返回
        } catch (Exception e) {
            System.out.println("公钥加密失败");
            e.printStackTrace();
        }
        return null;
    }
    /**加密-私钥-无分段*/
    private String encodePri(byte[] res,byte[] keyBytes){
        PKCS8EncodedKeySpec pk8 = new PKCS8EncodedKeySpec(keyBytes);
        try {
            KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM);
            Key priKey = kf.generatePrivate(pk8);
            Cipher cp = Cipher.getInstance(kf.getAlgorithm());
            cp.init(Cipher.ENCRYPT_MODE, priKey);
            return parseByte2HexStr(cp.doFinal(res));
        } catch (Exception e) {
            System.out.println("私钥加密失败");
            e.printStackTrace();
        }
        return null;
    }
    /**解密-公钥-无分段*/
    private byte[] decodePub(byte[] res,byte[] keyBytes){
        X509EncodedKeySpec x5 = new X509EncodedKeySpec(keyBytes);
        try {
            KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM);
            Key pubKey = kf.generatePublic(x5);
            Cipher cp = Cipher.getInstance(kf.getAlgorithm());
            cp.init(Cipher.DECRYPT_MODE, pubKey);
            return cp.doFinal(res);
        } catch (Exception e) {
            System.out.println("公钥解密失败");
            e.printStackTrace();
        }
        return null;
    }
    /**解密-私钥-无分段*/
    private byte[] decodePri(byte[] res,byte[] keyBytes){
        PKCS8EncodedKeySpec pk8 = new PKCS8EncodedKeySpec(keyBytes);
        try {
            KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM);
            Key priKey = kf.generatePrivate(pk8);
            Cipher cp = Cipher.getInstance(kf.getAlgorithm());
            cp.init(Cipher.DECRYPT_MODE, priKey);
            return cp.doFinal(res);
        } catch (Exception e) {
            System.out.println("私钥解密失败");
            e.printStackTrace();
        }
        return null;
    }
}

相关文章

相关文章

赶快留言冒泡

  • 评论 (0)
  • 引用通告 (0)
目前还没有任何评论.
目前还没有任何Trackbacks和Pingbacks.
吐个泡浮上去.