# Introduction

# Developers can operate by adding a signature. After the signature is generated, the developer can compare it with the information generated by the request in his own code to know whether the data is correct.
# Illustrate:
  • The process and method of signature with PayCools are mainly introduced here.

# Signature process

  1. Get the request parameters that need to be encrypted, excluding byte type parameters, such as files and byte streams, remove the sign field, and remove the parameters whose value is empty (Both of null and empty);

  2. Sort in ascending order according to the key value ASCII code of the first character (in ascending alphabetical order), if the same character is encountered, it will sort in ascending order according to the key value ASCII code of the second character, and so on;

  3. Combine the sorted parameters and their corresponding values into the format of parameter=parameter value, and connect these parameters with the & character. At this time, the generated string is the string to be signed.

# Signature original string example

# reqeust body
{
	"amount": 100.00,
	"appId": "f90addc4861540ef9312e87d8f360e08",
	"version":"1.0"
}

#step 2 sign origin string
amount=100.00&appId=f90addc4861540ef9312e87d8f360e08&version=1.0

# Generate signature

  • Sign the signature string with the merchant's private key
  • Key length is RSA2 4096 bits
  • For related code examples, please refer to the following encrypted java demo
@Slf4j
public class SignRSAUtils {

    public static final String SIGN_ALGORITHMS = "SHA256withRSA";

    /**
     * RSA sign
     * @param plainText plain text
     * @param privateKey private key
     * @return signature
     */
    public static String signWithSHA256(String plainText, String privateKey){
        try {
            privateKey = privateKey
                    .replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "")
                    .replace("-----END ENCRYPTED PRIVATE KEY-----", "")
                    .replace("\r", "")
                    .replace("\n", "")
                    .trim();

            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);

            Signature privateSignature = Signature.getInstance(SIGN_ALGORITHMS);
            privateSignature.initSign(priKey);
            privateSignature.update(plainText.getBytes(UTF_8));
            byte[] signature = privateSignature.sign();
            return java.util.Base64.getEncoder().encodeToString(signature);
        } catch (Exception e) {
            log.warn("RSA create sign error => exception:", e);
        }
        return null;
    }

    /**
     * Verify signature
     * @param plainText plain text
     * @param signature signature
     * @param publicKey public key
     * @return true or false
     */
    public static boolean verifyWithSHA256(String plainText, String signature, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            publicKey = publicKey.replace("-----BEGIN PUBLIC KEY-----", "")
                    .replace("-----END PUBLIC KEY-----", "")
                    .replace("\r", "")
                    .replace("\n", "")
                    .trim();
            byte[] encodedKey = Base64.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            Signature publicSignature = Signature.getInstance(SIGN_ALGORITHMS);
            publicSignature.initVerify(pubKey);
            publicSignature.update(plainText.getBytes(UTF_8));
            byte[] signatureBytes = java.util.Base64.getDecoder().decode(signature);
            return publicSignature.verify(signatureBytes);
        } catch (Exception e) {
            log.warn("RSA verify sign error => exception:", e);
        }
        return false;
    }
}