使用公鑰完成簽名驗證

在對接微信支付接口時,需要對微信支付返回的信息進行簽名驗證,防止中間人攻擊,替換微信支付返回的結果

整體過程

  • 微信支付生成簽名:私鑰 + 內容 -> signature
  • 調用方驗證簽名:公鑰 + 內容 驗證 signature

示例

  • 生成簽名
   /**
     * 生成簽名.
     *
     * @param originalData 原始數據
     * @param privateKey   私鑰
     * @return 簽名串
     */
    public static String sign(String originalData, PrivateKey privateKey) {
        String base64Sign = "";
        try {
            //返回指定簽名的Signature對象
            Signature sign = Signature.getInstance("SHA1withRSA");

            //初始化這個用於簽名的對象
            sign.initSign(privateKey);

            byte[] bysData = originalData.getBytes(StandardCharsets.UTF_8);

            //使用指定的byte數組更新要簽名的數據
            sign.update(bysData);
            //返回所有已經更新數據的簽名字節
            byte[] signByte = sign.sign();
            //對其進行Base64編碼
            BASE64Encoder encoder = new BASE64Encoder();
            base64Sign = encoder.encode(signByte);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return base64Sign;
    }
  • 驗證簽名
   /**
     * 驗證簽名.
     *
     * @param signStr      簽名串
     * @param originalData 原始數據
     * @param publicKey    公鑰
     * @return 是否驗證通過
     */
    public static boolean verify(String signStr, String originalData, PublicKey publicKey) {
        System.out.println("開始進行驗籤,原始數據爲:" + originalData);
        try {
            //將簽名數據
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] signed = decoder.decodeBuffer(signStr);

            //通過Signature的getInstance方法,獲取指定簽名算法的Signature對象
            Signature signature = Signature.getInstance("SHA1withRSA");
            //初始化用於驗證的對象
            signature.initVerify(publicKey);
            //使用指定的byte[]更新要驗證的數據
            signature.update(originalData.getBytes(StandardCharsets.UTF_8));
            //驗證傳入的簽名
            return signature.verify(signed);
        } catch (Exception e) {
            return false;
        }
    }
  • 測試
    public static void main(String[] args) throws Exception {
        String p12 = "KLFJDLJFL";
        byte[] decode = Base64.getDecoder().decode(p12);
        String keypasswd = "passwd";
        String keyalias = "tenpay certificate";
        KeyStore ks = KeyStore.getInstance("PKCS12");

        ks.load(new ByteArrayInputStream(decode), keypasswd.toCharArray());

        Enumeration<String> aliases = ks.aliases();
        while (aliases.hasMoreElements()) {
            System.out.println(aliases.nextElement());
        }
        PrivateKey prikey = (PrivateKey) ks.getKey(keyalias, keypasswd.toCharArray());
        Certificate cert = ks.getCertificate(keyalias);
        PublicKey pubkey = cert.getPublicKey();

        String originData = "hello world";
        String sign = sign(originData, prikey);

        boolean verify = verify(sign, originData, pubkey);
        System.out.println(verify);
    }

疑問

使用了HTTPS,爲什麼微信支付還要用公私鑰簽名呢?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章