当前位置: 移动技术网 > 移动技术>移动开发>Android > RSA 非对称加密算法的Java实现

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

2019年06月25日  | 移动技术网移动技术  | 我要评论
关于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 "";
    }

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网