All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jamiussiam.paddle.verifier.Verifier Maven / Gradle / Ivy

package com.jamiussiam.paddle.verifier;

import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class is responsible for verifying the supplied POST data
 * with the public signature.
 *
 * @see SecurityUtils
 * @see StringParser
 * @author Jamius Siam
 */
public class Verifier {
    private final PublicKey publicKey;

    private final SecurityUtils securityUtils;
    private final StringParser stringParser;

    /**
     * Creates a verifier instance from given Public Key
     * @param publicKeyString   The Public Key
     */
    public Verifier(String publicKeyString) {

        securityUtils = new SecurityUtils();
        stringParser = new StringParser();

        try {
            this.publicKey = securityUtils.getPublicKey(publicKeyString);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Invalid Public Key Given");
        }
    }

    /**
     * This method takes the postBody and publicKey and
     * returns a boolean with verification status. The p_signature
     * field must be present inside the postBody string.
     *
     * @param postBody            The body of the POST request sent from Paddle.
     * @return                    Returns true is data is valid.
     *
     * @throws IllegalArgumentException     It is thrown if the data is not a valid POST body.
     */
    public boolean verifyDataWithSignature(String postBody) {
        boolean isVerified = verifyInputData(postBody);

        // If data isn't a valid post body we throw an exception.
        if(!isVerified || !postBody.contains("p_signature")) {
            throw new IllegalArgumentException("The data supplied isn't a valid POST body.");
        }

        // Get the TreeMap from POST Body
        TreeMap postData = getSortedMapFromBody(postBody);

        // Get the p_signature
        byte[] pSignatureEncoded = securityUtils.getEncodedPSignature(postData);

        // Remove the p_signature from postData
        postData.remove("p_signature");


        // Get the serialized String
        String serializedString = stringParser.serialize(postData);


        // Verify the data
        try {
            Signature signer = Signature.getInstance("SHA1withRSA");
            signer.initVerify(publicKey);
            signer.update(serializedString.getBytes());

            isVerified = signer.verify(pSignatureEncoded);
        } catch (Exception e) {
            isVerified = false;
            e.printStackTrace();
        }

        return isVerified;
    }



    /**
     * Checks if the supplied data string is a valid POST body.
     *
     * @param data      The body of the POST request sent from Paddle.
     * @return          Returns true if it's a valid POST body.
     */
    private boolean verifyInputData(String data) {
        String regex = "&\\w+=";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(data);

        return matcher.find();
    }


    /**
     * Returns a sorted key value pair from POST body.
     * It includes the p_signature field.
     *
     * @param data  The POST body data.
     * @return      Returns a {@link TreeMap} with the data as key value pair.
     */
    private TreeMap getSortedMapFromBody(String data) {
        String[] split = data.split("&");
        TreeMap ret = new TreeMap<>();

        for(String s : split) {
            String[] half = s.split("=", 2);
            ret.put(half[0], half[1]);
        }

        return ret;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy