欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

RSA 非对称加密算法的Java实现

程序员文章站 2022-07-09 21:13:47
关于RSA的介绍Google一下很多,这里不做说明。项目开发中一般会把公钥放在本地进行加密,服务端通过私钥进行解密。Android项目开发中要用到这个加密算法,总结后实现如下: 使用如下: ......

关于rsa的介绍google一下很多,这里不做说明。项目开发中一般会把公钥放在本地进行加密,服务端通过私钥进行解密。android项目开发中要用到这个加密算法,总结后实现如下:

import android.content.context;
import android.util.base64;

import java.io.bufferedreader;
import java.io.ioexception;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.security.key;
import java.security.keyfactory;
import java.security.nosuchalgorithmexception;
import java.security.privatekey;
import java.security.publickey;
import java.security.spec.invalidkeyspecexception;
import java.security.spec.pkcs8encodedkeyspec;
import java.security.spec.x509encodedkeyspec;

import javax.crypto.cipher;


public class rsautil {

    /**
     * key_algorithm
     */
    public static final string key_algorithm = "rsa";
    /**
     * 加密key的长度等于1024
     */
    public static int keysize = 1024;
    /**
     * 解密时必须按照此分组解密
     */
    public static int decodelen = keysize / 8;
    /**
     * 加密时小于117即可
     */
    public static int encodelen = 110;//(default_key_size / 8) - 11;

    /**
     * 加密填充方式,android系统的rsa实现是"rsa/none/nopadding",而标准jdk实现是"rsa/none/pkcs1padding" ,这造成了在android机上加密后无法在服务器上解密的原因
     */
    public static final string ecb_pkcs1_padding = "rsa/ecb/pkcs1padding";


    public static final byte[] empty_byte_array = new byte[0];


    /**
     * 通过公钥加密
     */
    public static byte[] encryptpublickey(byte[] encrypteddata, string key) throws exception {
        if (encrypteddata == null) {
            throw new illegalargumentexception("input encryption data is null");
        }
        byte[] encode = new byte[]{};
        for (int i = 0; i < encrypteddata.length; i += encodelen) {
            byte[] subarray = subarray(encrypteddata, i, i + encodelen);
            byte[] dofinal = encryptbypublickey(subarray, key);
            encode = addall(encode, dofinal);
        }
        return encode;
    }

    /**
     * 通过私钥解密
     */
    public static byte[] decryptprivatekey(byte[] encode, string key) throws exception {
        if (encode == null) {
            throw new illegalargumentexception("input data is null");
        }
        byte[] buffers = new byte[]{};
        for (int i = 0; i < encode.length; i += decodelen) {
            byte[] subarray = subarray(encode, i, i + decodelen);
            byte[] dofinal = decryptbyprivatekey(subarray, key);
            buffers = addall(buffers, dofinal);
        }
        return buffers;
    }

    /**
     * 从字符串中加载公钥
     *
     * @param publickeystr 公钥数据字符串
     */
    private static publickey loadpublickey(string publickeystr) throws exception {
        try {
            byte[] buffer = decode(publickeystr);
            keyfactory keyfactory = keyfactory.getinstance(key_algorithm);
            //表示根据 asn.1 类型 subjectpublickeyinfo 进行编码的公用密钥的 asn.1 编码。
            x509encodedkeyspec keyspec = new x509encodedkeyspec(buffer);
            return keyfactory.generatepublic(keyspec);
        } catch (nosuchalgorithmexception e) {
            throw new exception("无此算法");
        } catch (invalidkeyspecexception e) {
            throw new exception("公钥非法");
        } catch (nullpointerexception e) {
            throw new exception("公钥数据为空");
        }
    }

    /**
     * 从字符串中加载私钥<br>
     * 加载时使用的是pkcs8encodedkeyspec(pkcs#8编码的key指令)。
     */
    private static privatekey loadprivatekey(string privatekeystr) throws exception {
        try {
            byte[] buffer = decode(privatekeystr);
            //表示按照 asn.1 类型 privatekeyinfo 进行编码的专用密钥的 asn.1 编码。
            pkcs8encodedkeyspec keyspec = new pkcs8encodedkeyspec(buffer);
            keyfactory keyfactory = keyfactory.getinstance(key_algorithm);
            return keyfactory.generateprivate(keyspec);
        } catch (nosuchalgorithmexception e) {
            throw new exception("无此算法");
        } catch (invalidkeyspecexception e) {
            throw new exception("私钥非法");
        } catch (nullpointerexception e) {
            throw new exception("私钥数据为空");
        }
    }


    /**
     * 用私钥解密
     */
    private static byte[] decryptbyprivatekey(byte[] data, string key) throws exception {
        if (data == null) {
            throw new illegalargumentexception("input data is null");
        }
        //取得私钥
        key privatekey = loadprivatekey(key);
        // 对数据解密
        cipher cipher = cipher.getinstance(ecb_pkcs1_padding);
        cipher.init(cipher.decrypt_mode, privatekey);

        return cipher.dofinal(data);
    }


    /**
     * 用公钥加密
     */
    private static byte[] encryptbypublickey(byte[] data, string key) throws exception {
        if (data == null) {
            throw new illegalargumentexception("input data is null");
        }
        // 取得公钥
        key publickey = loadpublickey(key);
        // 对数据加密
        cipher cipher = cipher.getinstance(ecb_pkcs1_padding);
        cipher.init(cipher.encrypt_mode, publickey);

        return cipher.dofinal(data);
    }


    /**
     * <p>
     * base64字符串解码为二进制数据
     * </p>
     */
    public static byte[] decode(string base64) {
        return base64.decode(base64, base64.default);
    }

    /**
     * <p>
     * 二进制数据编码为base64字符串
     * </p>
     */
    public static string encode(byte[] bytes) {
        return base64.encodetostring(bytes, base64.default);
    }


    /**
     * <p>produces a new {@code byte} array containing the elements
     * between the start and end indices.
     *
     * <p>the start index is inclusive, the end index exclusive.
     * null array input produces null output.
     *
     * @param array               the array
     * @param startindexinclusive the starting index. undervalue (&lt;0)
     *                            is promoted to 0, overvalue (&gt;array.length) results
     *                            in an empty array.
     * @param endindexexclusive   elements up to endindex-1 are present in the
     *                            returned subarray. undervalue (&lt; startindex) produces
     *                            empty array, overvalue (&gt;array.length) is demoted to
     *                            array length.
     * @return a new array containing the elements between
     * the start and end indices.
     * @since 2.1
     */
    private static byte[] subarray(final byte[] array, int startindexinclusive, int endindexexclusive) {
        if (array == null) {
            return null;
        }
        if (startindexinclusive < 0) {
            startindexinclusive = 0;
        }
        if (endindexexclusive > array.length) {
            endindexexclusive = array.length;
        }
        final int newsize = endindexexclusive - startindexinclusive;
        if (newsize <= 0) {
            return empty_byte_array;
        }

        final byte[] subarray = new byte[newsize];
        system.arraycopy(array, startindexinclusive, subarray, 0, newsize);
        return subarray;
    }

    /**
     * <p>adds all the elements of the given arrays into a new array.
     * <p>the new array contains all of the element of {@code array1} followed
     * by all of the elements {@code array2}. when an array is returned, it is always
     * a new array.
     *
     * @param array1 the first array whose elements are added to the new array.
     * @param array2 the second array whose elements are added to the new array.
     * @return the new byte[] array.
     * @since 2.1
     */
    private static byte[] addall(final byte[] array1, final byte... array2) {
        if (array1 == null) {
            return clone(array2);
        } else if (array2 == null) {
            return clone(array1);
        }
        final byte[] joinedarray = new byte[array1.length + array2.length];
        system.arraycopy(array1, 0, joinedarray, 0, array1.length);
        system.arraycopy(array2, 0, joinedarray, array1.length, array2.length);
        return joinedarray;
    }

    /**
     * <p>clones an array returning a typecast result and handling
     * {@code null}.
     *
     * <p>this method returns {@code null} for a {@code null} input array.
     *
     * @param array the array to clone, may be {@code null}
     * @return the cloned array, {@code null} if {@code null} input
     */
    private static byte[] clone(final byte[] array) {
        if (array == null) {
            return null;
        }
        return array.clone();
    }


    /**
     * 读取密钥信息
     */
    public static string readstring(inputstream in) throws ioexception {
        bufferedreader br = new bufferedreader(new inputstreamreader(in));
        string readline = null;
        stringbuilder sb = new stringbuilder();
        while ((readline = br.readline()) != null) {
            if (readline.charat(0) == '-') {
                continue;
            } else {
                sb.append(readline);
                sb.append('\r');
            }
        }

        return sb.tostring();
    }
}

使用如下:

  /**
     * 获取加密数据
     *
     * @param encryptstr 待加密字符串
     * rsa_public_key.pem 为本地公钥
     */
    public string getencryptdata(context context, string encryptstr) {

        try {
            inputstream inpublic = context.getresources().getassets().open("rsa_public_key.pem");
            string publickey = readstring(inpublic);
            byte[] encodeddata = encryptpublickey(encryptstr.getbytes(), publickey);

            return encode(encodeddata);
        } catch (ioexception e) {
            e.printstacktrace();
        } catch (exception e) {
            e.printstacktrace();
        }
        return "";
    }