package com.chinacreator.video.util;

import com.alibaba.druid.util.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RsaUtil {

    public static void main(String[] args) throws Exception {

        String str = "caller=HuaweiWallet&phoneNumber=18673197465&producCode=1011&spid=123456&timestamp=20220630155542";

        // RSA生成方法 http://www.metools.info/code/c80.html

        String publicKey = "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBTKK9bNrwIsY5ApEkYH3+3" +
                "x0yoqHWoImtZl9ZULn6V9LlFfLL2EWVYi93K4g0nm6nT1BAdq5wTTmdGUJQH32bT" +
                "wMo07QXWqTg5bm4p2ZNeprAehKa2Uh6Ey1nAqlGPV8w32PmekiHKApslqiJ0Q0FQ" +
                "bWdvhcPuZUhRqsYx+S55d3kO4Haez4hDoYloVEypkfU4kPe2DwkpB7hT199lAewd" +
                "NrRS9oQo0V/+SG6blzplyLnIaXAUlKzngP11bZGz6xAKZqauMjCxUX1UPLmhJ/nN" +
                "k+CW5D0SY/0MuZv6UY9rBwQN/IQScGcbUTrCYpIbPJuR2/NiU24EWQ/qxcKELCFh" +
                "AgMBAAE=";

        String privateKey = "MIIEoQIBAAKCAQBTKK9bNrwIsY5ApEkYH3+3x0yoqHWoImtZl9ZULn6V9LlFfLL2" +
                "EWVYi93K4g0nm6nT1BAdq5wTTmdGUJQH32bTwMo07QXWqTg5bm4p2ZNeprAehKa2" +
                "Uh6Ey1nAqlGPV8w32PmekiHKApslqiJ0Q0FQbWdvhcPuZUhRqsYx+S55d3kO4Hae" +
                "z4hDoYloVEypkfU4kPe2DwkpB7hT199lAewdNrRS9oQo0V/+SG6blzplyLnIaXAU" +
                "lKzngP11bZGz6xAKZqauMjCxUX1UPLmhJ/nNk+CW5D0SY/0MuZv6UY9rBwQN/IQS" +
                "cGcbUTrCYpIbPJuR2/NiU24EWQ/qxcKELCFhAgMBAAECggEAJPQocK0zA937K+iV" +
                "fr3IoJ9VBoHNvwiEkcyydrgukm6swh8227hBRAbraZPoaph28GYFP1oaQk4OAKYg" +
                "EhuJc0Hx2XEWrhyGmqbjF3/TSDVkgDtMZiq52yMOYFqPYdaPLqYhzwB7OWzNCwC+" +
                "zNFyPc5QL7POrKqfZ4MvDdgAegNGNYFqz4ZF/kme6eDfRWBUVDcLC6xbpc41hcsA" +
                "eb8fLzfSoyRZDcbV0t/XGYnEOG7AZbdgg0SwNAELMjeSsW2hhjvpBxOWd9CALqNA" +
                "T6avg4aG7N5DisIKAKoLVgzBkyklHrq8PlUR4ZySm+Ch6a6NfZgu8jTsAsWWBqFS" +
                "B07nDQKBgQCf4FnEF5FCR6/JFORhKE8ciYTiuTii4ddPhdrXrKuLDoj0c88JwB5T" +
                "scTz038SPf8Zer5FrUDll1/R4FN0qbxJNVWrwnI3HE1G61qt0IlHpXLknqOcHoVK" +
                "8rc6Puo1Xajn0h4CPpUKk5aKyyowSOR1ozj0ysYTb2zAFQPV5ST11wKBgQCFKDxP" +
                "oQ0ESg7xLZRIu5IaNfCeaLDjc1gTv+kXZThIIANcCmBSxbyoy5JToFQFXJUYybgn" +
                "24iGaHn+l2O3Jr+Ua8xy2xz9N74potwqd7J9gEBTlodsFmki5ICXyqUx4Zpox+rk" +
                "lgXsFmISBIARoj1c04n/uPcbqda5gpbj1YvLhwKBgFNTTdXK5rVhwXePAPy2Uo0w" +
                "C2dTW/ZguKREwmt4Hiwqliy6EyUk0WmTlG/0Qh1S3Jr+Ax8zjkhbHeC4Bycds/l/" +
                "57fOb1LT2F7nGWrP7ky+KWSIXgNnUNdgKykbU1wfBYJVW7iVv340r9iEzOc/hnrd" +
                "aDkFWjkU8Nwn18jqVdofAoGAEPrJfgn2Y/ahoyWBxCiO/+Ki9UA6VjauI46URZR1" +
                "sdTLOOBl2gg2/3s+BIXsUOa2aHvIjOSUqzcFX26km4VIZr+8SWUhdDS4fgyzcILk" +
                "8tX43e/TAvh0natvrmt71zmCfBwKGu36gVl1VgDW5+i9VGnxLffDIvbsV6mMXi8r" +
                "7V8CgYBkAWkbE0FAn6vG5ku9kROO3Nq8FDN2R2zGyiX8jSC/IBu1q3FqPA4LzO6q" +
                "z70f/+EteWYZGx9eaV4u9uDelNS7L3ME2PHOuF6WeKklnMG3RcFe7wgRnrIkMyvl" +
                "NtdWSabvr8mxBjqM892rKfsWLp+LCcyzy1J2J6z61HL9IzuNpg==";

        String plainData = RsaUtil.encrypt(str, publicKey);

        System.out.println("plainData = " + plainData);

        String strR = RsaUtil.decrypt(plainData, privateKey);

        System.out.println("strR = " + strR);

        String signStr = RsaUtil.signByRSA(str, privateKey);

        System.out.println("sign result = " + RsaUtil.verifyRSASign(str, publicKey, signStr));

    }

    public static final Charset UTF_8 = Charset.forName("UTF-8");

    private static final Pattern BLANK_PATTERN = Pattern.compile("\\s*|\t|\r|\n");

    static {

        if (Security.getProvider("BC") == null) {

            Security.addProvider(new BouncyCastleProvider());

        }

    }



    public static String encrypt(String source, String enPublicKey) throws Exception {

        try {

            PublicKey key = getPublicKey(enPublicKey);

            Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA-256AndMGF1Padding");

            cipher.init(1, key);

            byte[] b = source.getBytes(StandardCharsets.UTF_8);

            return new String(Base64Util.getEncoder().encode(cipher.doFinal(b)), StandardCharsets.UTF_8);

        } catch (Exception var8) {

            throw new Exception("encrypt fail.", var8);

        }

    }



    public static String decrypt(String plainData, String encryptPrivateKey) throws Exception {

        try {

            PrivateKey privateKey = getPrivateKey(encryptPrivateKey);

            Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA-256AndMGF1Padding");

            cipher.init(2, privateKey);

            byte[] b = Base64Util.getMimeDecoder().decode(replaceBlank(plainData).getBytes(StandardCharsets.UTF_8));

            return new String(cipher.doFinal(b), StandardCharsets.UTF_8);

        } catch (Exception var8) {

            throw new Exception("decrypt fail.", var8);

        }

    }



    public static String signByRSA(String plainData, String encryptPrivateKey) throws Exception {

        try {

            PrivateKey privateKey = getPrivateKey(encryptPrivateKey);

            Signature signature = Signature.getInstance("SHA256WithRSA/PSS");

            signature.initSign(privateKey);

            signature.update(plainData.getBytes(UTF_8));

            return encodeBase64(signature.sign());

        } catch (GeneralSecurityException var5) {

            throw new Exception("sign by rsa fail.", var5);

        }

    }



    public static boolean verifyRSASign(String plainData, String encryptPublicKey, String signData) throws Exception {

        try {

            PublicKey publicKey = getPublicKey(encryptPublicKey);

            Signature signature = Signature.getInstance("SHA256WithRSA/PSS");

            signature.initVerify(publicKey);

            signature.update(plainData.getBytes(UTF_8));

            return signature.verify(decodeBase64(signData));

        } catch (GeneralSecurityException var6) {

            throw new Exception("check rsa sign fail.", var6);

        }

    }



    private static String replaceBlank(String str) {

        if (StringUtils.isEmpty(str)) {

            return str;

        } else {

            Matcher matcher = BLANK_PATTERN.matcher(str);

            return matcher.replaceAll("");

        }

    }



    private static PublicKey getPublicKey(String key) throws GeneralSecurityException {

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodeBase64(key));

        return keyFactory.generatePublic(keySpec);

    }



    private static PrivateKey getPrivateKey(String key) throws GeneralSecurityException {

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodeBase64(key));

        return keyFactory.generatePrivate(keySpec);

    }



    public static byte[] decodeBase64(String input) {

        Objects.requireNonNull(input, "decodeBase64 params is null");

        byte[] encodeInput = input.getBytes(UTF_8);

        return Base64Util.getMimeDecoder().decode(encodeInput);

    }



    public static String encodeBase64(byte[] input) {

        Objects.requireNonNull(input, "encodeBase64 params is null");

        byte[] encoded = Base64Util.getEncoder().encode(input);

        return new String(encoded, UTF_8);

    }

}
