zoukankan      html  css  js  c++  java
  • RSAUtils

    package com.xxx.common.utils;

    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.lang3.ArrayUtils;

    import javax.crypto.Cipher;
    import java.security.*;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;

    public class RSAUtils {
    private static final String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMBMrifYyHbyMvBOuUujkC55GgWo1zntp4pjBisqGOHTu4QLLMBFogWwr1khZUXkgJEOOJxyhso7twEARaYdvGo6jB2ZMlByNBgg4Lk2+Xyqcn9Zh0MZD5n3KwXDUFmI/GkwI9X5Bo7IRyvaPFqxTvo7kWsuqyxu7B4RIq4xfQLwIDAQAB";
    private static final String privateKeyStr = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIwEyuJ9jIdvIy8E65S6OQLnkaBajXOe2nimMGKyoY4dO7hAsswEWiBbCvWSFlReSAkQ44nHKGyju3AQBFph28ajqMHZkyUHI0GCDguTb5fKpyf1mHQxkPmfcrBcNQWYj8aTAj1fkGjshHK9o8WrFO+juRay6rLG7sHhEirjF9AvAgMBAAECgYA3IlP5Z1KEqeCCzT8uaz2zxRd0uvNkCbMhOt9mncw7t4sifGdrKnOKtg7Ur9eXFSDsYPgX8pIaZUaTU9tC87GkJ1+bT4EkxgCuKHCeASs6OQBMLGXaXxyJY0ZIIJFAjrmm0KUvh0qAOmIuamo63rMhQXSYVOuWiwJ0jCVcnFbR8QJBAOwlax1/Z8s6XWpD2/GW39Wbm6HCKP1mrHtZYaOB+xHRGIm2NClcISlmpAzlw1++SibVqN+L2mZ4KgESUe3iOaUCQQCXymuELq38OkZFjcSOVM5f4VYJkwwVAcM2eWuKhGe3eH0+9xPwzWmzQos1HFE1wI39tpeI7ihJrTfXfSG8NrJDAkA/5mgz1TP69FIu3Sn5F8B+Btt4TBfXah8mSat4GUYdLh2btigrQPjgQRwHOW1CzTU3iP1ncGqq671CCPkOi/bZAkBblMib3uIgXTSKwIdH7Mj7NmSHsE3I2uBiHI4S6+H741mFxOMmFXlhq5N7/tLMoJnK6wCwoCh0k2suu5PAECwrAkAgTOy4ty0ZUOme+N4cGOLAACfUHhJi8PaFSrFFl35PgzQRt6jS8LLiqFeaM7IiaGEop2wSLKoyeSoe1WOQSb33";

    // public static void main( String[] args ) throws Exception {
    // //生成公钥和私钥
    // getKeyPair();
    // //加密字符串
    // String password="<p><div style=\"text-align: center;\"><img src=\"https://img.eoliao.com/b60a6c68-0118-4758-bde2-c9e69394168b.jpg\" style=\"font-family: &quot;Microsoft Yahei&quot;, sans-serif; font-size: 14px; text-align: initial; max- 100%;\"></div>国际米兰主帅孔蒂希望今夏能够大幅度补强中场,目前蓝黑军团基本上已经敲定了比达尔的加盟,接下来他们还希望签下另外一名强援——坎特。《米兰体育报》的最新消息表示,坎特本人十分愿意加盟到国际米兰,但是切尔西方面希望得到至少5000万欧元的转会费。<br><br>《米兰体育报》称,孔蒂一直以来都十分欣赏坎特,在他执教切尔西期间,法国国脚便是他的爱将,在执教国际米兰之后,孔蒂也曾多次希望将坎特引进到阵中。这个夏天的转会窗开启之后,孔蒂便将坎特视作中场引援的头号目标,并且他也已经亲自说服坎特转投蓝黑军团,接下来的事情便是国际米兰高层去说服切尔西高层放人了。<br><div style=\"text-align: center;\"><img src=\"https://img.eoliao.com/768ad2a3-f04f-4c70-9f8c-32d66137a50e.jpg\" style=\"font-family: &quot;Microsoft Yahei&quot;, sans-serif; font-size: 14px; text-align: initial; max- 100%;\"></div>据了解,目前国际米兰高层已经开始与切尔西方面进行接触,但暂时来看情况不是很乐观。因为切尔西对于坎特的标价高达5000万欧元,这已经明显超出了国际米兰方面的预期。当然了,考虑到孔蒂强烈要求得到坎特的意愿,国际米兰方面还是打算满足切尔西的要价,但前提是他们要通过卖人来募集转会资金。<br><br>在目前的国际米兰阵中,有包括布罗佐维奇、什克里尼亚尔以及埃里克森几名重量级球员属于可出售的范围。此前曾有消息称国际米兰希望用埃里克森与坎特进行互换,但是切尔西方面对此提议并不感兴趣。而布罗佐维奇目前则吸引到了摩纳哥的关注,但是前法甲冠军也满足不了国际米兰2200万欧元的要价。<br><div style=\"text-align: center;\"><img src=\"https://img.eoliao.com/e6527cdd-ef42-4397-b736-6f0ee3927456.jpg\" style=\"font-family: &quot;Microsoft Yahei&quot;, sans-serif; font-size: 14px; text-align: initial; max- 100%;\"></div>《米兰体育报》最后还透露,如果国际米兰最终无法说服切尔西放人,那么他们会转攻其他目标,目前马竞后腰托马斯被蓝黑军团视作第二选择。不过要想说服马竞放人同样难度很大,个中原因其实也是因为钱,床单军团为托马斯标出的价格同样是5000万欧元,国际米兰还是难以支付这个价格。</p>";
    // System.out.println("随机生成的公钥为:"+keyMap.get(0));
    // System.out.println("随机生成的私钥为:"+keyMap.get(1));
    // String passwordEn=encrypt(password,keyMap.get(0));
    // System.out.println(password+"\t加密后的字符串为:"+passwordEn);
    // String passwordDe=decrypt(passwordEn,keyMap.get(1));
    // System.out.println("还原后的字符串为:"+passwordDe);
    // }
    // /**
    // * 随机生成密钥对
    // * @throws NoSuchAlgorithmException
    // */
    public static void getKeyPair() throws Exception {
    //KeyPairGenerator类用于生成公钥和密钥对,基于RSA算法生成对象
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    //初始化密钥对生成器,密钥大小为96-1024位
    keyPairGen.initialize(1024,new SecureRandom());
    //生成一个密钥对,保存在keyPair中
    KeyPair keyPair = keyPairGen.generateKeyPair();
    PrivateKey privateKey = keyPair.getPrivate();//得到私钥
    PublicKey publicKey = keyPair.getPublic();//得到公钥
    //得到公钥字符串
    String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
    System.out.println(publicKeyString);
    //得到私钥字符串
    String privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()));
    System.out.println(privateKeyString);
    }

    /**
    * RSA最大加密明文大小
    */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
    * RSA最大解密密文大小
    */
    private static final int MAX_DECRYPT_BLOCK = 128;

    public static final String SIGN_ALGORITHMS = "SHA256withRSA";

    private static String ALGORITHM_RSA = "RSA";

    /**
    * 使用公钥将数据加密
    * @param sourceData
    * @param publicKey
    * @return
    */
    public static String publicEncrypt(String sourceData, String publicKey){
    return rsaEncrypt(sourceData,publicKey,false);
    }

    /**
    * 使用私钥将数据加密
    * @param sourceData
    * @param privateKey
    * @return
    */
    public static String privateEncrypt(String sourceData, String privateKey){
    return rsaEncrypt(sourceData,privateKey,true);
    }

    /**
    * 使用公钥解密
    * @param encryptedData
    * @param privateKey
    * @return
    */
    public static String publicDecrypt(String encryptedData, String privateKey) {
    return rsaDecrypt(encryptedData,privateKey,false);
    }

    /**
    * 使用私钥解密
    * @param encryptedData
    * @param privateKey
    * @return
    */
    public static String privateDecrypt(String encryptedData, String privateKey) {
    return rsaDecrypt(encryptedData,privateKey,true);
    }

    protected static String rsaEncrypt(String sourceData, String key,boolean isPrivate){
    try {
    Key key1 = isPrivate ? loadPrivateKey(key) : loadPublicKey(key);
    byte[] data = sourceData.getBytes();
    byte[] dataReturn = new byte[0];
    Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
    cipher.init(Cipher.ENCRYPT_MODE, key1);

    // 加密时超过117字节就报错。为此采用分段加密的办法来加密
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < data.length; i += MAX_ENCRYPT_BLOCK) {
    byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i,i + MAX_ENCRYPT_BLOCK));
    sb.append(new String(doFinal));
    dataReturn = ArrayUtils.addAll(dataReturn, doFinal);
    }

    return Base64.encodeBase64URLSafeString(dataReturn);
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    }

    protected static String rsaDecrypt(String encryptedData, String key,boolean isPrivate){
    try {
    Key key1 = isPrivate ? loadPrivateKey(key) : loadPublicKey(key);
    byte[] data = Base64.decodeBase64(encryptedData);

    Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
    cipher.init(Cipher.DECRYPT_MODE, key1);

    // 解密时超过128字节就报错。为此采用分段解密的办法来解密
    byte[] dataReturn = new byte[0];
    for (int i = 0; i < data.length; i += MAX_DECRYPT_BLOCK) {
    byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + MAX_DECRYPT_BLOCK));
    dataReturn = ArrayUtils.addAll(dataReturn, doFinal);
    }

    return new String(dataReturn);
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    }

    /**
    * 私钥加签名
    * @param encryptData
    * @param privateKey
    * @return
    */
    public static String rsaSign(String encryptData, String privateKey) {
    try {
    Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
    signature.initSign(loadPrivateKey(privateKey));
    signature.update(encryptData.getBytes());
    byte[] signed = signature.sign();
    return Base64.encodeBase64URLSafeString(signed);
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    /**
    * 公钥验签
    * @param encryptStr
    * @param sign
    * @param publicKey
    * @return
    * @throws Exception
    */
    public static boolean verifySign(String encryptStr, String sign, String publicKey)throws Exception {
    try {
    Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
    signature.initVerify(loadPublicKey(publicKey));
    signature.update(encryptStr.getBytes());
    return signature.verify(Base64.decodeBase64(sign));
    } catch (NoSuchAlgorithmException e) {
    throw new Exception(String.format("验证数字签名时没有[%s]此类算法", SIGN_ALGORITHMS));
    } catch (InvalidKeyException e) {
    throw new Exception("验证数字签名时公钥无效");
    } catch (SignatureException e) {
    throw new Exception("验证数字签名时出现异常");
    }
    }

    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
    byte[] buffer = Base64.decodeBase64(publicKeyStr);
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
    return keyFactory.generatePublic(keySpec);
    }

    public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
    byte[] buffer = Base64.decodeBase64(privateKeyStr);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
    return keyFactory.generatePrivate(keySpec);
    }

    public static String urlsafe_encode (String encryptStr){
    return encryptStr.replaceAll("\\+","-").replaceAll("/","_").replaceAll("=","").replaceAll("(\r\n|\r|\n|\n\r)","");

    }

    public static String urlsafe_decode(String encryptStr){
    encryptStr= encryptStr.replaceAll("-","+").replaceAll("_","/");
    int mob = encryptStr.length()%4;
    if(mob>0){
    encryptStr+="====".substring(mob);
    }
    return encryptStr;
    }



    public static void main(String[ ] asdfs) throws Exception {
    getKeyPair();

    //加密
    String data = "<p><div style=\"text-align: center;\"><img src=\"https://img.eoliao.com/b60a6c68-0118-4758-bde2-c9e69394168b.jpg\" style=\"font-family: &quot;Microsoft Yahei&quot;, sans-serif; font-size: 14px; text-align: initial; max- 100%;\"></div>国际米兰主帅孔蒂希望今夏能够大幅度补强中场,目前蓝黑军团基本上已经敲定了比达尔的加盟,接下来他们还希望签下另外一名强援——坎特。《米兰体育报》的最新消息表示,坎特本人十分愿意加盟到国际米兰,但是切尔西方面希望得到至少5000万欧元的转会费。<br><br>《米兰体育报》称,孔蒂一直以来都十分欣赏坎特,在他执教切尔西期间,法国国脚便是他的爱将,在执教国际米兰之后,孔蒂也曾多次希望将坎特引进到阵中。这个夏天的转会窗开启之后,孔蒂便将坎特视作中场引援的头号目标,并且他也已经亲自说服坎特转投蓝黑军团,接下来的事情便是国际米兰高层去说服切尔西高层放人了。<br><div style=\"text-align: center;\"><img src=\"https://img.eoliao.com/768ad2a3-f04f-4c70-9f8c-32d66137a50e.jpg\" style=\"font-family: &quot;Microsoft Yahei&quot;, sans-serif; font-size: 14px; text-align: initial; max- 100%;\"></div>据了解,目前国际米兰高层已经开始与切尔西方面进行接触,但暂时来看情况不是很乐观。因为切尔西对于坎特的标价高达5000万欧元,这已经明显超出了国际米兰方面的预期。当然了,考虑到孔蒂强烈要求得到坎特的意愿,国际米兰方面还是打算满足切尔西的要价,但前提是他们要通过卖人来募集转会资金。<br><br>在目前的国际米兰阵中,有包括布罗佐维奇、什克里尼亚尔以及埃里克森几名重量级球员属于可出售的范围。此前曾有消息称国际米兰希望用埃里克森与坎特进行互换,但是切尔西方面对此提议并不感兴趣。而布罗佐维奇目前则吸引到了摩纳哥的关注,但是前法甲冠军也满足不了国际米兰2200万欧元的要价。<br><div style=\"text-align: center;\"><img src=\"https://img.eoliao.com/e6527cdd-ef42-4397-b736-6f0ee3927456.jpg\" style=\"font-family: &quot;Microsoft Yahei&quot;, sans-serif; font-size: 14px; text-align: initial; max- 100%;\"></div>《米兰体育报》最后还透露,如果国际米兰最终无法说服切尔西放人,那么他们会转攻其他目标,目前马竞后腰托马斯被蓝黑军团视作第二选择。不过要想说服马竞放人同样难度很大,个中原因其实也是因为钱,床单军团为托马斯标出的价格同样是5000万欧元,国际米兰还是难以支付这个价格。</p>";
    String privateEncryptStr = RSAUtils.privateEncrypt(data, privateKeyStr);//私钥加密
    String publicEncryptStr = RSAUtils.publicEncrypt(data, publicKeyStr);//公钥加密
    // String privateEncryptSign = RSAUtils.rsaSign(privateEncryptStr,privateKeyStr);
    // String publicEncryptSign = RSAUtils.rsaSign(publicEncryptStr,privateKeyStr);
    System.out.println("source:" + data);
    // System.out.println("private encryptStr: " + privateEncryptStr);
    // System.out.println("public encryptStr: " + publicEncryptStr);
    // System.out.println("private encrypt sign: " + privateEncryptSign);
    // System.out.println("public encrypt sign: " + publicEncryptSign);
    //
    // System.out.println("public decrypt:" + RSAUtils.publicDecrypt(privateEncryptStr, publicKeyStr));
    // System.out.println("private decrypt:" + RSAUtils.privateDecrypt(publicEncryptStr, privateKeyStr));
    // System.out.println("verifySign1: " + RSAUtils.verifySign(privateEncryptStr,privateEncryptSign,publicKeyStr));
    // System.out.println("verifySign2: " + RSAUtils.verifySign(publicEncryptStr,publicEncryptSign,publicKeyStr));
    //
    // System.out.println("\r\n");
    // publicEncryptStr = "WopnO2LnolZ7XpOwA_ktOhfkkaQQJQgkJudk3ZH_-ob36GQFv968nE1UBXxNekA9pIHBcvcl0ZWfwFhk-kyOF2FmQvpPY9LkqiCV0T32vhJet0n93ti2PBoFILxvChjzdOgSG9M0flH78Vm696Q4mHo7VMt_XMoHDTd3Rbagvt8";
    // privateEncryptStr = "Fwb5BtLRveCWbx7FkXarl1zVOdwDvbDTl7gv-vPHXpj-T2wm9GlUDn3X0wnHHXkE8cqAT6PcE0g0ide6beP9_ysHMLgnC6wVqkomIKsi6C9TcGd4d6XQBjeJgdgccvDcD-7pcKrV9W-_Z7jkYkwwrjPGPd_uckEHR_cDXyOX4PU";
    // System.out.println("php >>>> private decrypt: " + RSAUtils.privateDecrypt(publicEncryptStr, privateKeyStr));
    // System.out.println("php >>>> public decrypt: " + RSAUtils.publicDecrypt(privateEncryptStr, publicKeyStr));
    //
    // publicEncryptStr = "T2LFtY3dF_b6OBO07BN-3LtMSEBZqDukovDZ4HGCff8wosvlowf6IFJ3U7LFBIeHfiHBKiFuAV8-pFltCfTXtA4AwgVUnwbBMBWBfIJiLDi02ev30V-5BcYEuSF-cEdnSUd7WecrX4rHhzYLueGuj8H6c7RRbSbrJ6_3EFfU-K0";
    // System.out.println("js >>>> private decrypt: " + RSAUtils.privateDecrypt(publicEncryptStr, privateKeyStr));
    }
    }
  • 相关阅读:
    POJ 1001 Exponentiation
    POJ 2105 IP Address
    条款1:视C++为一个语言联邦
    条款2:尽量使用const ,enum,inline替换define
    走台阶问题
    Oracle之分页问题
    Oracle之子查询:Top-N问题
    Facade——外观模式
    PROXY——代理模式
    C++ 内联函数
  • 原文地址:https://www.cnblogs.com/michaelcnblogs/p/15735984.html
Copyright © 2011-2022 走看看