Java,Android使用RSA 算法加解密

RSA算法:

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。

RSA工具类:


public class RSAHelper {

    private static final String RSA = "RSA"; // RSA/ECB/PKCS1Padding

    /**
     * 读取密钥信息
     * 
     * @param in
     * @return
     * @throws IOException
     */
    public static String readKey(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("");
            }
        }
        return sb.toString();
    }

    /**
     * 从文件中输入流中加载公钥 ,android 可以将公钥放在assets目录
     * 
     * @param in
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(InputStream in) throws Exception {
        try {
            return getPublicKey(readKey(in));
        } catch (IOException e) {
            throw new Exception("公钥数据流读取错误");
        } catch (NullPointerException e) {
            throw new Exception("公钥输入流为空");
        }
    }

    /**
     * 读取公钥信息
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        try {
            byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("私钥非法");
        } catch (NullPointerException e) {
            throw new Exception("私钥数据为空");
        }

    }

    /**
     * 从文件中输入流中加载私钥 ,android 可以将私钥放在assets目录
     * 
     * @param in
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(InputStream in) throws Exception {
        try {
            return getPrivateKey(readKey(in));
        } catch (IOException e) {
            throw new Exception("私钥数据读取错误");
        } catch (NullPointerException e) {
            throw new Exception("私钥输入流为空");
        }
    }

    /**
     * 读取私钥信息
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        try {
            byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("私钥非法");
        } catch (NullPointerException e) {
            throw new Exception("私钥数据为空");
        }

    }

    /**
     * 读取Key的信息
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static String getKeyString(Key key) throws Exception {
        byte[] keyBytes = key.getEncoded();
        String s = (new BASE64Encoder()).encode(keyBytes);
        return s;
    }

    /**
     * RSA加密
     * 
     * @param plainText
     *            明文
     * @param key
     *            密钥
     * @return
     * @throws Exception
     */
    public static byte[] encryptData(byte[] plainText, PublicKey key)
            throws Exception {
        // 加解密类
        Cipher cipher = Cipher.getInstance(RSA);
        // 加密
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] enBytes = cipher.doFinal(plainText);
        return enBytes;
    }

    /**
     * RSA 解密
     * 
     * @param enBytes
     *            加密数据
     * @param key
     *            私钥
     * @return
     * @throws Exception
     */
    public static byte[] decryptData(byte[] enBytes, PrivateKey key)
            throws Exception {
        // 加解密类
        Cipher cipher = Cipher.getInstance(RSA);
        // 解密
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] deBytes = cipher.doFinal(enBytes);
        return deBytes;
    }

    public static void main(String[] args) throws Exception {

        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
        // 密钥位数
        keyPairGen.initialize(1024);
        // 密钥对
        KeyPair keyPair = keyPairGen.generateKeyPair();

        // 公钥
        PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        // 私钥
        PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        String publicKeyString = getKeyString(publicKey);
        System.out.println("public:\n" + publicKeyString);

        String privateKeyString = getKeyString(privateKey);
        System.out.println("private:\n" + privateKeyString);

        String text = "这里是测试RSA算法的明文";
        byte[] plainText = text.getBytes();
        //将公钥字符串还原公钥信息
        publicKey = getPublicKey(publicKeyString);
        byte[] enBytes = encryptData(plainText, publicKey);

        //将私钥字符串还原私钥信息
        privateKey = getPrivateKey(privateKeyString);
        byte[] deBytes = decryptData(enBytes, privateKey);
        publicKeyString = getKeyString(publicKey);

        System.out.println("公钥:\n" + publicKeyString);

        privateKeyString = getKeyString(privateKey);
        System.out.println("私钥:\n" + privateKeyString);

        String s = new String(deBytes);
        System.out.println(s);

    }
}

在Android使用:

String text = "这里是测试RSA算法的明文";

// 从Assets文件中得到公钥
InputStream inPublic = getResources().getAssets().open("pub.key");
PublicKey publicKey = RSAHelper.getPublicKey(inPublic);
// 从Assets文件中得到私钥
InputStream inPri = getResources().getAssets().open("pri.key");
PrivateKey priKey = RSAHelper.getPrivateKey(RSAUtil.readKey(inPri));

// 加密
byte[] encryptByte = RSAHelper.encryptData(text.getBytes(),
        publicKey);
// 解密
byte[] decryptByte = RSAHelper.decryptData(encryptByte, priKey);
String decrypt = new String(decryptByte);

Log.i("RSA", "加密字符串:" + text);
Log.i("RSA", "解密字符串:" + decrypt);

备注:
import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
在Android可以用自带的Base64代替
在java中需要引用附件中的sun.misc.BASE64Decoder.jar

相关资源下载

点击下载资源

后继
在android加密后,在服务器解密,一直出现:
javax.crypto.BadPaddingException: Blocktype mismatch: 0

继续查资料:参考错误说明

Cipher.getInstance(“RSA”)
改成:
Cipher.getInstance(“RSA”, “BC”);
但是没有效果.
猜想,问题原因已查到,就是配置问题。
最后修改:
在加解密方法里面,
将 Cipher cipher = Cipher.getInstance(RSA);
替换成:Cipher cipher = Cipher.getInstance(“RSA/None/PKCS1Padding”);
最后成功.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值