# Sign

Signature is the verification of the body of the messages during the interaction between the Pyvio and the merchant. Signature usually occurs in post http request. There is also a webhook message used by Pyvio to notify merchants of data changes.

Pyvio uses the RSA private key to decrypt, and the RSA public key to sign.Therefore, during the API interaction, there are merchant RSA public and private keys and Pyvio RSA public and private keys.

The signing rules are as follows:

  1. The merchant sends a request to Pyvio, the merchant uses its own RSA private key to sign, and Pyvio uses the merchant's RSA public key to verify the signature;
  2. Pyvio sends a notification to the merchant, Pyvio uses its own RSA private key to sign, and the merchant uses the Pyvio RSA public key to verify the signature;
  3. Signing is to encrypt the http request body, app_id,timestamp,For specific rules, see the following signature example;
  4. Whether it is the public and private keys of the merchant or the platform, the generation method is to use the PKCS8 padding method and 2048 length Tool (opens new window);
  5. sign out and base64 as the signed string;
  6. Put the encrypted string in the header Sign.

# Sample code

    package com.pyvio.developer.sdk.aop;
    
    import org.apache.commons.codec.binary.Base64;
    
    import java.security.KeyFactory;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    public class SignTest {
    
        /**
         * 参数签名(${appId}${timestamp}${requestBody})
         * @param content
         * @param privateKey
         * @return
         * @throws Exception
         */
        public static String sign(String content,String privateKey) throws Exception {
            Signature signature = Signature.getInstance("SHA256WithRSA");
            PrivateKey prk = getPrivateKeyFromPKCS8("RSA",privateKey);
            signature.initSign(prk);
            byte[] bytes = content.getBytes("UTF-8");
            signature.update(bytes);
            byte[] signed = signature.sign();
            return Base64.encodeBase64String(signed);
        }
    
        public static boolean signCheck(String content,String sign, String publicKey) {
            try {
                PublicKey pubKey = getPublicKeyFromX509("RSA", publicKey);
                java.security.Signature signature = java.security.Signature.getInstance("SHA256WithRSA");
                signature.initVerify(pubKey);
                signature.update(content.getBytes("UTF-8"));
                return signature.verify(Base64.decodeBase64(sign.getBytes()));
            } catch (Exception e) {
                return false;
            }
        }
    
        private static PrivateKey getPrivateKeyFromPKCS8(String algorithm, String privateKey) throws Exception {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            byte[] encodedKey = privateKey.getBytes();
            encodedKey = Base64.decodeBase64(encodedKey);
            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
        }
    
        private static PublicKey getPublicKeyFromX509(String algorithm, String publicKey) throws Exception {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            byte[] encodedKey = publicKey.getBytes();
            encodedKey = Base64.decodeBase64(encodedKey);
            return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
        }
    
        public static void main(String[] args) throws Exception {
            //partner app id
            String appId = "1569641270953589504";
            //request time
            Long timestamp = 1666332361000L;
            //partner rsa private key
            String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALxGyg3/boLT2I8dQnC3Njc2XIDJgZM/G4wqsDDUVoy/PQ2THA39sKHiLsTg71zVbQZ4+UYWm1aTlms7KuBuOmvmdIzKuI04NbSuDeAbAtnraizhELSOpVQFNom2tIGHw4/46VuF3bE0rgFjKGqrRI9xOVEcDGZlP4h9JatQEgytAgMBAAECgYADZ1dX9Awy+A+NlAFm4BQrcXFy1xt7GIGUHaSUCe3N7sxY45uB+F+vyVh6aJm74QlCaJvmQv62Lg5t1HOQ2pcHD6/r7G0lykjYJ3JEAmF3KKm/FgPqX9MGqZCBNHp3oQaHMf8WwRfjxr/EBT1QfdItCGjiENJ4bjSJo9qzEPtjSQJBAMx/r6clsTUdpeskw60UMJG17Af5Fc/SNCsq8hdmCqva0QtT1l/vprmwEH1hKXlA9au9cIESp0ceABH86jE9Vu8CQQDrsTt/S6iiWAiJKA8eYWSEcPyQXoB+tveg4ZoKUwG+fT5t9tXOuPZGmC7CWsAATfO88/ySGqNyIlFgSDvTM3YjAkB+c9JdLCyI6L1pSwGIq/xgjbrXL0oyiQvjSZoLp/ifTh6Hv57HEfzpw5pevU8VAHspaGoCFlPD4SQv+1GhgwmXAkAd6grBJ1sp7751mg4BLx9Q5/5GXJg2fQaE9t1UPiDUipTn5BJTAIrRfvNAW8BOyZYL/3OpH5RrIgvuCnz9W2S9AkB19MQtKSc3Ba36Jo3C0kvTdeSDBR4o+ah+bzhwg/Hj8EKYp4IoyW8mx32WXtSLGp8OjupPlZ65PUkzy838Eo8v";
            //partner rsa public key
            String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8RsoN/26C09iPHUJwtzY3NlyAyYGTPxuMKrAw1FaMvz0NkxwN/bCh4i7E4O9c1W0GePlGFptWk5ZrOyrgbjpr5nSMyriNODW0rg3gGwLZ62os4RC0jqVUBTaJtrSBh8OP+Olbhd2xNK4BYyhqq0SPcTlRHAxmZT+IfSWrUBIMrQIDAQAB";
            // post request json body,read from request stream
            String requestBody = "{\"grant_type\":\"client_credentials\",\"app_id\":\"1569641270953589505\",\"app_secret\":\"bc2ead7739f447c49032b4aef7818c47\"}";
    
            //generate rule
            String signContent = appId + timestamp + requestBody;
            String sign = sign(signContent,privateKey);
            System.out.println(sign);
            System.out.println(signCheck(signContent,sign,publicKey));
        }
    }
    
    
    // Make sure to add code blocks to your code group