作者归档:RAE

Android RSA公钥、私钥加密和解密

在Android中使用 RSA公钥、私钥加密和解密

公钥私钥加密

     /**
     * 公钥加密
     * @throws Exception
     */
    @Test
    public void testPublicKeyEncrypt() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+aOZLmOizkK325oR6SktKald6YSR8pYSFYbionJjiQKtpFjKEaAsBkiGj8WPGDMNJrYGezVvAC0PQYbxqdbjx0ybQ6JlT/nzkLIAbzQjoThS3PQDjsW/gBeELkgY4VIrqDB8VNYNohAg29zaFAP3bFkpjFwcct93c70ZvL8mz6wIDAQAB";

        String text = "test123";
        String result = "We0llfPLbCYjK6bKtauY2Ym3+vOuziObjdscv6v1uiXPDcflK81zlH2TNTLAkXzDJ9u5MgsuIp0QL6qGwFlaZU/yRV91YIJfFdOA0a1xZ+qMe5N/r6h7nCpUD+Omwc0p7pSjfkv2hUlFG062OcfVfVf2ssittW9qhLKS91WDypY=";

        // 加载公钥
        X509EncodedKeySpec data = new X509EncodedKeySpec(Base64.decode(pubKey.getBytes(), Base64.DEFAULT));
        KeyFactory factory = KeyFactory.getInstance("RSA");
        PublicKey key = factory.generatePublic(data);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encryptData = cipher.doFinal(text.getBytes());
        String encrypt = Base64.encodeToString(encryptData, Base64.DEFAULT);

        Assert.assertEquals("加密:" + encrypt, encrypt, result);

    }

    /**
     * 私钥加密
     * @throws Exception
     */
    @Test
    public void testPrivateKey() throws Exception {
        String priKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL5o5kuY6LOQrfbmhHpKS0pqV3phJHylhIVhuKicmOJAq2kWMoRoCwGSIaPxY8YMw0mtgZ7NW8ALQ9BhvGp1uPHTJtDomVP+fOQsgBvNCOhOFLc9AOOxb+AF4QuSBjhUiuoMHxU1g2iECDb3NoUA/dsWSmMXBxy33dzvRm8vybPrAgMBAAECgYBVGTjjzIEjz6OQV1IZ/Z5Msd5K2aOe+bKSkiwfX22MoO561urY9k8E8rSKOtYmq4mUIjFuMcWxvNcgCK5WvipbUrYaGI1wTza34ncxO7rm7/mYB1BPhX+d5lPCTNKhYix7JlDGwaC/npxQJtR9FalhxFIU+Lmr2JZN4I3swDcikQJBAPwifquvVJ75TV/Js5xGpF5E4T8t9z8O3ceQfmszglv4hXuJJLKd2UFSa2bWGP3z0x2t3qX4ZbkJ9qUrFEsUIycCQQDBVCodYi9eVXdcD0Mosv/KZjO2mx51tS6XczWfUxoyRpYdWxLfyq5vBgGEEJt4QipkgGXKnwuUppGkXBdHMdOdAkABHKHUXfyQiublcj1Bhio5ZDJeFfTOKWGe/KsiC+MaRrlH9y3bP8jyecuRc4Y+sHGQ4vBlaPgB3eJhjhQT1K3nAkB2xoa5VsFTa57RaG8SaibM6s2KuvKTzqS5V4byQ9QsX0GK95E4/QT+IOp9gNaDo+L3rArd2aj7wvpnyExk6S/hAkEAxsFtWDChCZmt62vRmz3mmrtq9scg4LplA3U0vN2glv+lc+OoRQlG0lCRFak9BH0EWqbntREeRRMn6TOI0QZKYw==";
        String text = "raetest";

        // 加载公钥
        PKCS8EncodedKeySpec data = new PKCS8EncodedKeySpec(Base64.decode(priKey.getBytes(), Base64.DEFAULT));
        KeyFactory factory = KeyFactory.getInstance("RSA");
        PrivateKey key = factory.generatePrivate(data);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encryptData = cipher.doFinal(text.getBytes());
        String encrypt = Base64.encodeToString(encryptData, Base64.DEFAULT);

        Assert.assertEquals("加密:" + encrypt, encrypt, "12312");
    }

Android 微信支付签名问题

1、微信调用统一订单后会返回下面结果

{
    "return_code": "SUCCESS",
    "return_msg": "OK",
    "appid": "APPID",
    "mch_id": "商户号",
    "nonce_str": "随机字符串",
    "sign": "081675D3A89B1A735613CF2D777E6F06",
    "prepay_id": "wx201706052018103dd047b0880123350695",
    "result_code": "FAIL",
    "err_code": "ORDERPAID",
    "err_code_des": "该订单已支付"
}

2、Android 需要服务端再次签名返回,因为如果在APP端做校验的话会暴露appkey,对APP的安全性有影响

3、对下面的字符进行拼接之后签名产生sign字段,签名格式查看官方签名

注意:这里的key为商户的key,而不是AppSecret;timestamp为当前的时间戳

"appid=" + appid + "&noncestr=" + nonce_str + "&package=Sign=WXPay" + "&partnerid=" + mch_id + "&prepayid=" + prepayid + "&timestamp=" + timeStamp + "&key=" + key;

4、最后返回的下面的字段:

{
    "appid": "第1步的APPID",
    "mch_id": "第1步的mch_id",
    "prepay_id": "第1步的prepay_id",
    "nonce_str": "第1步的nonce_str",
    "sign": "第3步的签名,不是第1步的签名",
    "timestamp":"第3步的时间戳"
}