签名算法PHP和Java的不同实现

来源:互联网 发布:mac os 安装ipython 编辑:程序博客网 时间:2024/05/21 10:41
数字签名是密码学理论中的一个重要分支。它的提出是为了对电子文档进行签名,以 替代传统纸质文档上的手写签名,因此它必须具备 5 个特性。
(1)签名是可信的。
(2)签名是不可伪造的。
(3)签名是不可重用的。
(4)签名的文件是不可改变的。

(5)签名是不可抵赖的。


基于以上原因,我们要求请求我们的API时必须添加签名,以下分别是PHP和Java发送请求的实例:

PHP添加签名是一件so easy的事情,因为它有openssl这一强大的工具,请看示例:

    //签名    public static function genSignatureForAPI($params)    {        $requestSignature = NULL;        $privateKey=null;        $rawRequestBody = json_encode($params);//POST请求之前也要对要post的数据做json_encode        $privateKey=Util::getPrivateKey();        if ($privateKey) {            $signResult = openssl_sign($rawRequestBody, $requestSignature, $privateKey, 'sha256');            if (!$signResult) {                throw new \Exception("Generate signature failed");            }        }        return base64_encode($requestSignature);    }

    //API post请求示例    function testAPI()    {        $data=array(            "order_no"=> "owFW468460681780",            "app"=> array(                        "id"=> "app_WTGWGw4365wgwtwerewE"            ),            "metadata"=> array("metadata1"=> "VeryExcellent!"),        );        $headers=array(            'Content-type: application/json;charset=UTF-8',            'Signature: '.Util::genSignatureForAPI($data)        );        $httprequestor=new HttpRequestor();        $response=$httprequestor->curlHttpRequestForAPI($headers,"POST",$BaseUrl."/v1/tests/",$data);    }

而Java的实现就比较麻烦了,请看示例:

    /**     * 将map转换为json字符串     * @param <span style="font-family: Arial, Helvetica, sans-serif;">map</span>     * @return     */    public static String createJSONString(Map<String, Object> map) {        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();        return gson.toJson(map);    }    /**     * 生成请求签名     * @param privateKeyPath     * @param jsonStr     * @return     * @throws IOException     */public static String genSignatureForAPI(String privateKeyPath, String jsonStr) throws IOException {    String keyString="";        if (privateKeyPath == null) {            return null;        }else        {            FileInputStream inputStream = new FileInputStream(privateKeyPath);            byte[] keyBytes = new byte[inputStream.available()];            inputStream.read(keyBytes);            inputStream.close();            keyString = new String(keyBytes, CHARSET);        }        String trimmedPrivateKey = keyString                .replaceAll("(-+BEGIN (RSA )?PRIVATE KEY-+\\r?\\n|-+END (RSA )?PRIVATE KEY-+\\r?\\n?)", "");        byte[] privateKeyBytes = Base64.decodeBase64(trimmedPrivateKey);        DerInputStream derReader = new DerInputStream(privateKeyBytes);        DerValue[] seq = derReader.getSequence(0);        if (seq.length < 9) {            System.out.println("Could not parse a PKCS1 private key.");            return null;        }        // skip version seq[0];        BigInteger modulus = seq[1].getBigInteger();        BigInteger publicExp = seq[2].getBigInteger();        BigInteger privateExp = seq[3].getBigInteger();        BigInteger prime1 = seq[4].getBigInteger();        BigInteger prime2 = seq[5].getBigInteger();        BigInteger exp1 = seq[6].getBigInteger();        BigInteger exp2 = seq[7].getBigInteger();        BigInteger crtCoef = seq[8].getBigInteger();        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);        try {            KeyFactory keyFactory = KeyFactory.getInstance("RSA");            PrivateKey privateKey = keyFactory.generatePrivate(spec);            Signature signature = Signature.getInstance("SHA256withRSA");            signature.initSign(privateKey);            signature.update(jsonStr.getBytes(CHARSET));            byte[] signBytes = signature.sign();            return Base64.encodeBase64String(signBytes).replaceAll("\n|\r", "");        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (InvalidKeySpecException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (SignatureException e) {            e.printStackTrace();        }        return null;    }
具体每一个方法的含义还请你自行查阅以便于深入了解!!!

        /** * Post请求API示例 * @throws Exception */@Testpublic void testAPI() throws Exception {Map<String, Object> chargeParams =APIJsonMap.createChargeMap(apiparams, category);String jsonStr=APIUtils.createJSONString(chargeParams);//添加签名字段String signature=APIUtils.genSignatureForAPI(apiparams.getPrivateKeyPath(),jsonStr);if(signature!=null){headers.put("Signature",signature);}System.out.println(signature);final Response res=APIUtils.doPost(headers, jsonStr, "tests/", 200);BaseCheck.verifyCommonParamsForChargeResult(res, category, apiparams);}


至于doPost方法,其实我是封装了rest_assured框架的一些方法来完成的,具体还请前往https://github.com/rest-assured/rest-assured学习。

0 0
原创粉丝点击