zoukankan      html  css  js  c++  java
  • 加密证书和RSA加密解密

    最近一直在做与第三方的支付业务,因为数据涉及到了钱,所以交互的数据保密性非常的重要!主要应用的是RSA加密机制,整理一下共享给大家! 
    1、生成加密证书

    1)产生证书的工具:openssl;openssl的官方推荐网站下载:http://slproweb.com/products/Win32OpenSSL.html

    2)配置文件:我下载的是win-64位轻量版的:Win64OpenSSL-1_0_2f.exe,下载之后解压到C盘(我刚开始是解压到其他盘的,但是出现错误:can’t open config file: /usr/local/ssl/openssl.cnf,有人说配置环境变量:set OPENSSL_CONF=..confopenssl.cnf ;我是了不好使,大家查出来是什么问题可以告诉我一下,哈哈)在C盘根目录依次建立usr/local/ssl/openssl.cnf文件后,下载地址:http://download.csdn.net/detail/qq_32347977/9396321

    3)生成采用des3算法保护的私钥: 
    OpenSSL> genrsa -des3 -out private-rsa.key 1024 
    命令执行过程中的提示信息Enter pass phrase 的含义是输入用来保护私钥文件的密码(不要超过6位),我的是123456。

    4) 生成公钥证书: 
    OpenSSL> req -new -x509 -key private-rsa.key -days 750 -out public-rsa.cer 
    该过程除了最开始时需要输入私钥文件的保护密码之外,其他需要的输入均可直接回车忽略,不影响正常使用。

    5)生成PKCS12 格式Keystore: 
    OpenSSL> pkcs12 -export -name test-alias -in public-rsa.cer -inkey private-rsa.key -out user-rsa.pfx 
    这里写图片描述 
    这样就ok了。

    AES工具类:

    package com.alex.util;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.UnsupportedEncodingException;
    import java.security.Key;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    
    public class AES {
    
        public static final String CHAR_ENCODING = "UTF-8";
        public static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
         /**
         * 加密
         * 
         * @param / data
         *            待加密密内容
         * @param /key
         *            加密密钥
         * @return
         */
        public static byte[] encrypt(byte[] data, byte[] key) {
            if(key.length!=16){
                throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
            }
            try {
                SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec seckey = new SecretKeySpec(enCodeFormat,"AES");
                Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
                cipher.init(Cipher.ENCRYPT_MODE, seckey);// 初始化
                byte[] result = cipher.doFinal(data);
                return result; // 加密
            } catch (Exception e){
                throw new RuntimeException("encrypt fail!", e);
            }
        }
    
        /**
         * 解密
         * 
         * @param / content
         *            待解密内容
         * @param /password
         *            解密密钥
         * @return
         */
        public static byte[] decrypt(byte[] data, byte[] key) {
            if(key.length!=16){
                throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
            }
            try {
                SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
                Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
                cipher.init(Cipher.DECRYPT_MODE, seckey);// 初始化
                byte[] result = cipher.doFinal(data);
                return result; // 加密
            } catch (Exception e){
                throw new RuntimeException("decrypt fail!", e);
            }
        }
    
        public static String encryptToBase64(String data, String key){
            try {
                byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING), key.getBytes(CHAR_ENCODING));
                return new String(Base64.encode(valueByte));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("encrypt fail!", e);
            }
    
        }
    
        public static String decryptFromBase64(String data, String key){
            try {
                byte[] originalData = Base64.decode(data.getBytes());
                byte[] valueByte = decrypt(originalData, key.getBytes(CHAR_ENCODING));
                return new String(valueByte, CHAR_ENCODING);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("decrypt fail!", e);
            }
        }
    
        public static String encryptWithKeyBase64(String data, String key){
            try {
                byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING), Base64.decode(key.getBytes()));
                return new String(Base64.encode(valueByte));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("encrypt fail!", e);
            }
        }
    
        public static String decryptWithKeyBase64(String data, String key){
            try {
                byte[] originalData = Base64.decode(data.getBytes());
                byte[] valueByte = decrypt(originalData, Base64.decode(key.getBytes()));
                return new String(valueByte, CHAR_ENCODING);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("decrypt fail!", e);
            }
        }
    
        public static byte[] genarateRandomKey(){
            KeyGenerator keygen = null;
            try {
                keygen = KeyGenerator.getInstance(AES_ALGORITHM);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(" genarateRandomKey fail!", e);
            }
            SecureRandom random = new SecureRandom();
            keygen.init(random);
            Key key = keygen.generateKey();
            return key.getEncoded();
        }
    
        public static String genarateRandomKeyWithBase64(){
            return new String(Base64.encode(genarateRandomKey()));
        }
    }

    Base64工具类:

    package com.alex.util;
    
    import java.io.UnsupportedEncodingException;
    
    public class Base64  {
        /**
         * Chunk size per RFC 2045 section 6.8.
         *
         * <p>The {@value} character limit does not count the trailing CRLF, but counts
         * all other characters, including any equal signs.</p>
         *
         * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
         */
        static final int CHUNK_SIZE = 76;
    
        /**
         * Chunk separator per RFC 2045 section 2.1.
         *
         * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
         */
        static final byte[] CHUNK_SEPARATOR = "
    ".getBytes();
    
        /**
         * The base length.
         */
        static final int BASELENGTH = 255;
    
        /**
         * Lookup length.
         */
        static final int LOOKUPLENGTH = 64;
    
        /**
         * Used to calculate the number of bits in a byte.
         */
        static final int EIGHTBIT = 8;
    
        /**
         * Used when encoding something which has fewer than 24 bits.
         */
        static final int SIXTEENBIT = 16;
    
        /**
         * Used to determine how many bits data contains.
         */
        static final int TWENTYFOURBITGROUP = 24;
    
        /**
         * Used to get the number of Quadruples.
         */
        static final int FOURBYTE = 4;
    
        /**
         * Used to test the sign of a byte.
         */
        static final int SIGN = -128;
    
        /**
         * Byte used to pad output.
         */
        static final byte PAD = (byte) '=';
    
        // Create arrays to hold the base64 characters and a
        // lookup for base64 chars
        private static byte[] base64Alphabet = new byte[BASELENGTH];
        private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
    
        // Populating the lookup and character arrays
        static {
            for (int i = 0; i < BASELENGTH; i++) {
                base64Alphabet[i] = (byte) -1;
            }
            for (int i = 'Z'; i >= 'A'; i--) {
                base64Alphabet[i] = (byte) (i - 'A');
            }
            for (int i = 'z'; i >= 'a'; i--) {
                base64Alphabet[i] = (byte) (i - 'a' + 26);
            }
            for (int i = '9'; i >= '0'; i--) {
                base64Alphabet[i] = (byte) (i - '0' + 52);
            }
    
            base64Alphabet['+'] = 62;
            base64Alphabet['/'] = 63;
    
            for (int i = 0; i <= 25; i++) {
                lookUpBase64Alphabet[i] = (byte) ('A' + i);
            }
    
            for (int i = 26, j = 0; i <= 51; i++, j++) {
                lookUpBase64Alphabet[i] = (byte) ('a' + j);
            }
    
            for (int i = 52, j = 0; i <= 61; i++, j++) {
                lookUpBase64Alphabet[i] = (byte) ('0' + j);
            }
    
            lookUpBase64Alphabet[62] = (byte) '+';
            lookUpBase64Alphabet[63] = (byte) '/';
        }
    
        private static boolean isBase64(byte octect) {
            if (octect == PAD) {
                return true;
            } else if (base64Alphabet[octect] == -1) {
                return false;
            } else {
                return true;
            }
        }
    
        /**
         * Tests a given byte array to see if it contains
         * only valid characters within the Base64 alphabet.
         *
         * @param arrayOctect byte array to test
         * @return true if all bytes are valid characters in the Base64
         *         alphabet or if the byte array is empty; false, otherwise
         */
        public static boolean isArrayByteBase64(byte[] arrayOctect) {
    
            arrayOctect = discardWhitespace(arrayOctect);
    
            int length = arrayOctect.length;
            if (length == 0) {
                // shouldn't a 0 length array be valid base64 data?
                // return false;
                return true;
            }
            for (int i = 0; i < length; i++) {
                if (!isBase64(arrayOctect[i])) {
                    return false;
                }
            }
            return true;
        }
    
        /**
         * Encodes binary data using the base64 algorithm but
         * does not chunk the output.
         *
         * @param binaryData binary data to encode
         * @return Base64 characters
         */
        public static byte[] encodeBase64(byte[] binaryData) {
            return encodeBase64(binaryData, false);
        }
    
        /**
         * Encodes binary data using the base64 algorithm and chunks
         * the encoded output into 76 character blocks
         *
         * @param binaryData binary data to encode
         * @return Base64 characters chunked in 76 character blocks
         */
        public static byte[] encodeBase64Chunked(byte[] binaryData) {
            return encodeBase64(binaryData, true);
        }
    
        /**
         * Decodes a byte[] containing containing
         * characters in the Base64 alphabet.
         *
         * @param pArray A byte array containing Base64 character data
         * @return a byte array containing binary data
         */
        public static byte[] decode(byte[] pArray) {
            return decodeBase64(pArray);
        }
    
        /**
         * Encodes binary data using the base64 algorithm, optionally
         * chunking the output into 76 character blocks.
         *
         * @param binaryData Array containing binary data to encode.
         * @param isChunked if isChunked is true this encoder will chunk
         *                  the base64 output into 76 character blocks
         * @return Base64-encoded data.
         */
        public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
            int lengthDataBits = binaryData.length * EIGHTBIT;
            int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
            int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
            byte encodedData[] = null;
            int encodedDataLength = 0;
            int nbrChunks = 0;
    
            if (fewerThan24bits != 0) {
                //data not divisible by 24 bit
                encodedDataLength = (numberTriplets + 1) * 4;
            } else {
                // 16 or 8 bit
                encodedDataLength = numberTriplets * 4;
            }
    
            // If the output is to be "chunked" into 76 character sections,
            // for compliance with RFC 2045 MIME, then it is important to
            // allow for extra length to account for the separator(s)
            if (isChunked) {
    
                nbrChunks =
                    (CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
                encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
            }
    
            encodedData = new byte[encodedDataLength];
    
            byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
    
            int encodedIndex = 0;
            int dataIndex = 0;
            int i = 0;
            int nextSeparatorIndex = CHUNK_SIZE;
            int chunksSoFar = 0;
    
            //log.debug("number of triplets = " + numberTriplets);
            for (i = 0; i < numberTriplets; i++) {
                dataIndex = i * 3;
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                b3 = binaryData[dataIndex + 2];
    
                //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
    
                l = (byte) (b2 & 0x0f);
                k = (byte) (b1 & 0x03);
    
                byte val1 =
                    ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                byte val2 =
                    ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
                byte val3 =
                    ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
    
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                //log.debug( "val2 = " + val2 );
                //log.debug( "k4   = " + (k<<4) );
                //log.debug(  "vak  = " + (val2 | (k<<4)) );
                encodedData[encodedIndex + 1] =
                    lookUpBase64Alphabet[val2 | (k << 4)];
                encodedData[encodedIndex + 2] =
                    lookUpBase64Alphabet[(l << 2) | val3];
                encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
    
                encodedIndex += 4;
    
                // If we are chunking, let's put a chunk separator down.
                if (isChunked) {
                    // this assumes that CHUNK_SIZE % 4 == 0
                    if (encodedIndex == nextSeparatorIndex) {
                        System.arraycopy(
                            CHUNK_SEPARATOR,
                            0,
                            encodedData,
                            encodedIndex,
                            CHUNK_SEPARATOR.length);
                        chunksSoFar++;
                        nextSeparatorIndex =
                            (CHUNK_SIZE * (chunksSoFar + 1)) +
                            (chunksSoFar * CHUNK_SEPARATOR.length);
                        encodedIndex += CHUNK_SEPARATOR.length;
                    }
                }
            }
    
            // form integral number of 6-bit groups
            dataIndex = i * 3;
    
            if (fewerThan24bits == EIGHTBIT) {
                b1 = binaryData[dataIndex];
                k = (byte) (b1 & 0x03);
                //log.debug("b1=" + b1);
                //log.debug("b1<<2 = " + (b1>>2) );
                byte val1 =
                    ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
                encodedData[encodedIndex + 2] = PAD;
                encodedData[encodedIndex + 3] = PAD;
            } else if (fewerThan24bits == SIXTEENBIT) {
    
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                l = (byte) (b2 & 0x0f);
                k = (byte) (b1 & 0x03);
    
                byte val1 =
                    ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                byte val2 =
                    ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
    
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] =
                    lookUpBase64Alphabet[val2 | (k << 4)];
                encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
                encodedData[encodedIndex + 3] = PAD;
            }
    
            if (isChunked) {
                // we also add a separator to the end of the final chunk.
                if (chunksSoFar < nbrChunks) {
                    System.arraycopy(
                        CHUNK_SEPARATOR,
                        0,
                        encodedData,
                        encodedDataLength - CHUNK_SEPARATOR.length,
                        CHUNK_SEPARATOR.length);
                }
            }
    
            return encodedData;
        }
    
        /**
         * Decodes Base64 data into octects
         *
         * @param base64Data Byte array containing Base64 data
         * @return Array containing decoded data.
         */
        public static byte[] decodeBase64(byte[] base64Data) {
            // RFC 2045 requires that we discard ALL non-Base64 characters
            base64Data = discardNonBase64(base64Data);
    
            // handle the edge case, so we don't have to worry about it later
            if (base64Data.length == 0) {
                return new byte[0];
            }
    
            int numberQuadruple = base64Data.length / FOURBYTE;
            byte decodedData[] = null;
            byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
    
            // Throw away anything not in base64Data
    
            int encodedIndex = 0;
            int dataIndex = 0;
            {
                // this sizes the output array properly - rlw
                int lastData = base64Data.length;
                // ignore the '=' padding
                while (base64Data[lastData - 1] == PAD) {
                    if (--lastData == 0) {
                        return new byte[0];
                    }
                }
                decodedData = new byte[lastData - numberQuadruple];
            }
    
            for (int i = 0; i < numberQuadruple; i++) {
                dataIndex = i * 4;
                marker0 = base64Data[dataIndex + 2];
                marker1 = base64Data[dataIndex + 3];
    
                b1 = base64Alphabet[base64Data[dataIndex]];
                b2 = base64Alphabet[base64Data[dataIndex + 1]];
    
                if (marker0 != PAD && marker1 != PAD) {
                    //No PAD e.g 3cQl
                    b3 = base64Alphabet[marker0];
                    b4 = base64Alphabet[marker1];
    
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    decodedData[encodedIndex + 1] =
                        (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                    decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
                } else if (marker0 == PAD) {
                    //Two PAD e.g. 3c[Pad][Pad]
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                } else if (marker1 == PAD) {
                    //One PAD e.g. 3cQ[Pad]
                    b3 = base64Alphabet[marker0];
    
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    decodedData[encodedIndex + 1] =
                        (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                }
                encodedIndex += 3;
            }
            return decodedData;
        }
    
        /**
         * Discards any whitespace from a base-64 encoded block.
         *
         * @param data The base-64 encoded data to discard the whitespace
         * from.
         * @return The data, less whitespace (see RFC 2045).
         */
        static byte[] discardWhitespace(byte[] data) {
            byte groomedData[] = new byte[data.length];
            int bytesCopied = 0;
    
            for (int i = 0; i < data.length; i++) {
                switch (data[i]) {
                case (byte) ' ' :
                case (byte) '
    ' :
                case (byte) '
    ' :
                case (byte) '	' :
                        break;
                default:
                        groomedData[bytesCopied++] = data[i];
                }
            }
    
            byte packedData[] = new byte[bytesCopied];
    
            System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
    
            return packedData;
        }
    
        /**
         * Discards any characters outside of the base64 alphabet, per
         * the requirements on page 25 of RFC 2045 - "Any characters
         * outside of the base64 alphabet are to be ignored in base64
         * encoded data."
         *
         * @param data The base-64 encoded data to groom
         * @return The data, less non-base64 characters (see RFC 2045).
         */
        static byte[] discardNonBase64(byte[] data) {
            byte groomedData[] = new byte[data.length];
            int bytesCopied = 0;
    
            for (int i = 0; i < data.length; i++) {
                if (isBase64(data[i])) {
                    groomedData[bytesCopied++] = data[i];
                }
            }
    
            byte packedData[] = new byte[bytesCopied];
    
            System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
    
            return packedData;
        }
    
        /**
         * Encodes a byte[] containing binary data, into a byte[] containing
         * characters in the Base64 alphabet.
         *
         * @param pArray a byte array containing binary data
         * @return A byte array containing only Base64 character data
         */
        public static byte[] encode(byte[] pArray) {
            return encodeBase64(pArray, false);
        }
    
    
         public static String decode(String cryptoStr) throws
           UnsupportedEncodingException {
           if(cryptoStr.length()<40)
             return "";
           try
           {
             String tempStr = new String(decode(cryptoStr.getBytes("UTF-8")));
             String result = tempStr.substring(40, tempStr.length());
             return new String(decode(result.getBytes("UTF-8")));
           }
           catch(ArrayIndexOutOfBoundsException ex)
           {
             return "";
           }
         }
    
         /**
          * Decodes Base64 data into octects
          *
          * @param encoded string containing Base64 data
          * @return Array containind decoded data.
          */
         public static byte[] decode2(String encoded) {
    
             if (encoded == null) {
                 return null;
             }
    
             char[] base64Data = encoded.toCharArray();
             // remove white spaces
             int len = removeWhiteSpace(base64Data);
    
             if (len % FOURBYTE != 0) {
                 return null;//should be divisible by four
             }
    
             int numberQuadruple = (len / FOURBYTE);
    
             if (numberQuadruple == 0) {
                 return new byte[0];
             }
    
             byte decodedData[] = null;
             byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
             char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
    
             int i = 0;
             int encodedIndex = 0;
             int dataIndex = 0;
             decodedData = new byte[(numberQuadruple) * 3];
    
             for (; i < numberQuadruple - 1; i++) {
    
                 if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
                     || !isData((d3 = base64Data[dataIndex++]))
                     || !isData((d4 = base64Data[dataIndex++]))) {
                     return null;
                 }//if found "no data" just return null
    
                 b1 = base64Alphabet[d1];
                 b2 = base64Alphabet[d2];
                 b3 = base64Alphabet[d3];
                 b4 = base64Alphabet[d4];
    
                 decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                 decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                 decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
             }
    
             if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
                 return null;//if found "no data" just return null
             }
    
             b1 = base64Alphabet[d1];
             b2 = base64Alphabet[d2];
    
             d3 = base64Data[dataIndex++];
             d4 = base64Data[dataIndex++];
             if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
                 if (isPad(d3) && isPad(d4)) {
                     if ((b2 & 0xf) != 0)//last 4 bits should be zero
                     {
                         return null;
                     }
                     byte[] tmp = new byte[i * 3 + 1];
                     System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                     tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                     return tmp;
                 } else if (!isPad(d3) && isPad(d4)) {
                     b3 = base64Alphabet[d3];
                     if ((b3 & 0x3) != 0)//last 2 bits should be zero
                     {
                         return null;
                     }
                     byte[] tmp = new byte[i * 3 + 2];
                     System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                     tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                     tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                     return tmp;
                 } else {
                     return null;
                 }
             } else { //No PAD e.g 3cQl
                 b3 = base64Alphabet[d3];
                 b4 = base64Alphabet[d4];
                 decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                 decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                 decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
    
             }
    
             return decodedData;
         }
    
         private static boolean isWhiteSpace(char octect) {
             return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
         }     
    
         private static boolean isData(char octect) {
             return (octect < BASELENGTH && base64Alphabet[octect] != -1);
         }
    
         private static boolean isPad(char octect) {
             return (octect == PAD);
         }
    
         /**
          * remove WhiteSpace from MIME containing encoded Base64 data.
          *
          * @param data  the byte array of base64 data (with WS)
          * @return      the new length
          */
         private static int removeWhiteSpace(char[] data) {
             if (data == null) {
                 return 0;
             }
    
             // count characters that's not whitespace
             int newSize = 0;
             int len = data.length;
             for (int i = 0; i < len; i++) {
                 if (!isWhiteSpace(data[i])) {
                     data[newSize++] = data[i];
                 }
             }
             return newSize;
         } 
    }
    

    Decipher工具类:

    package com.alex.util;
    
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    
    public class Decipher {
        /**
         * 解密
         * 
         * @param merchant_id
         * @param data
         * @param encryptkey
         * @return
         * @throws 
         */
        public static String decryptData(Map<String, String> map) throws Exception {
    
            String encryptkey = map.get("encryptkey");
            String data = map.get("data");
    
            // 获取自己私钥解密
            PrivateKey pvkformPfx = RSA.getPvkformPfx("F:\miyao\demo\user-rsa.pfx",
                    "123456");
            String decryptData = RSA.decrypt(encryptkey, pvkformPfx);
    
            String post = AES.decryptFromBase64(data, decryptData);
    
            return post;
        }
    
        /**
         * 加密
         * 
         * @param merchant_id
         * @param data
         * @param encryptkey
         * @return
         * @throws 
         */
        public static Map<String, String> encryptData(String json) throws Exception {
            System.out.println("json数据=============>" + json);
    
            // 获取公钥
            PublicKey pubKeyFromCrt = RSA.getPubKeyFromCRT("F:\miyao\demo\public-rsa.cer");
            // 随机生成16数字
            String key = getRandom(16);
            // 使用RSA算法将自己随机生成的AESkey加密
            String encryptKey = RSA.encrypt(key, pubKeyFromCrt);
            // 使用AES算法用随机生成的AESkey,对json串进行加密
            String encryData = AES.encryptToBase64(json, key);
    
            System.out.println("密文key============>" + encryptKey);
            System.out.println("密文数据===========>" + encryData);
    
            Map<String, String> map = new HashMap<String, String>();
            map.put("data", encryData);
            map.put("encryptkey", encryptKey);
    
            return map;
        }
    
        public static Random random = new Random();
    
        public static String getRandom(int length) {
            StringBuilder ret = new StringBuilder();
            for (int i = 0; i < length; i++) {
                boolean isChar = (random.nextInt(2) % 2 == 0);// 输出字母还是数字
                if (isChar) { // 字符串
                    int choice = (random.nextInt(2) % 2 == 0) ? 65 : 97; // 取得大写字母还是小写字母
                    ret.append((char) (choice + random.nextInt(26)));
                } else { // 数字
                    ret.append(Integer.toString(random.nextInt(10)));
                }
            }
            return ret.toString();
        }
    
        public static void main(String[] args) {
    
        }
    
    }

    RSA工具类:

    package com.alex.util;
    
    /*
     --------------------------------------------**********--------------------------------------------
    
     该算法于1977年由美国麻省理工学院MIT(Massachusetts Institute of Technology)的Ronal Rivest,Adi Shamir和Len Adleman三位年轻教授提出,并以三人的姓氏Rivest,Shamir和Adlernan命名为RSA算法,是一个支持变长密钥的公共密钥算法,需要加密的文件快的长度也是可变的!
    
     所谓RSA加密算法,是世界上第一个非对称加密算法,也是数论的第一个实际应用。它的算法如下:
    
     1.找两个非常大的质数p和q(通常p和q都有155十进制位或都有512十进制位)并计算n=pq,k=(p-1)(q-1)。
    
     2.将明文编码成整数M,保证M不小于0但是小于n。
    
     3.任取一个整数e,保证e和k互质,而且e不小于0但是小于k。加密钥匙(称作公钥)是(e, n)。
    
     4.找到一个整数d,使得ed除以k的余数是1(只要e和n满足上面条件,d肯定存在)。解密钥匙(称作密钥)是(d, n)。
    
     加密过程: 加密后的编码C等于M的e次方除以n所得的余数。
    
     解密过程: 解密后的编码N等于C的d次方除以n所得的余数。
    
     只要e、d和n满足上面给定的条件。M等于N。
    
     --------------------------------------------**********--------------------------------------------
     */
    
    
    import javax.crypto.Cipher;
    
    import org.apache.commons.lang.StringUtils;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.math.BigInteger;
    import java.security.*;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateFactory;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.TreeMap;
    
    public class RSA {
    
        /** 指定key的大小 */
        private static int KEYSIZE = 1024;
        public static final String CHAR_ENCODING = "UTF-8";
        public static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";
        /**
         * 生成密钥对
         */
        public static Map<String, String> generateKeyPair() throws Exception {
            /** RSA算法要求有一个可信任的随机数源 */
            SecureRandom sr = new SecureRandom();
            /** 为RSA算法创建一个KeyPairGenerator对象 */
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
            kpg.initialize(KEYSIZE, sr);
            /** 生成密匙对 */
            KeyPair kp = kpg.generateKeyPair();
            /** 得到公钥 */
            Key publicKey = kp.getPublic();
            byte[] publicKeyBytes = publicKey.getEncoded();
            String pub = new String(Base64.encodeBase64(publicKeyBytes),
                    CHAR_ENCODING);
            /** 得到私钥 */
            Key privateKey = kp.getPrivate();
            byte[] privateKeyBytes = privateKey.getEncoded();
            String pri = new String(Base64.encodeBase64(privateKeyBytes),
                    CHAR_ENCODING);
    
            Map<String, String> map = new HashMap<String, String>();
            map.put("publicKey", pub);
            map.put("privateKey", pri);
            RSAPublicKey rsp = (RSAPublicKey) kp.getPublic();
            BigInteger bint = rsp.getModulus();
            byte[] b = bint.toByteArray();
            byte[] deBase64Value = Base64.encodeBase64(b);
            String retValue = new String(deBase64Value);
            map.put("modulus", retValue);
            return map;
        }
    
        /**
         * 通过PFX文件获得私钥
         *
         * @param //文件路径
         * @param //PFX密码
         * @return PrivateKey
         */
        public static PrivateKey getPvkformPfx(String strPfx, String strPassword)
                throws Exception {
            PrivateKey prikey = null;
            char[] nPassword = null;
            if ((strPassword == null) || strPassword.trim().equals("")) {
                nPassword = null;
            } else {
                nPassword = strPassword.toCharArray();
            }
            KeyStore ks = getKsformPfx(strPfx, strPassword);
            String keyAlias = getAlsformPfx(strPfx, strPassword);
            prikey = (PrivateKey) ks.getKey(keyAlias, nPassword);
            return prikey;
        }
    
        /**
         * 通过PFX文件获得KEYSTORE
         *
         * @param //文件路径
         * @param //PFX密码
         * @return KeyStore
         */
        public static KeyStore getKsformPfx(String strPfx, String strPassword)
                throws Exception {
            FileInputStream fis = null;
            Security
                    .addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    
            KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
            fis = new FileInputStream(strPfx);
            // If the keystore password is empty(""), then we have to set
            // to null, otherwise it won't work!!!
            char[] nPassword = null;
            if ((strPassword == null) || strPassword.trim().equals("")) {
                nPassword = null;
            } else {
                nPassword = strPassword.toCharArray();
            }
            ks.load(fis, nPassword);
            if (null != fis) {
    
                fis.close();
    
            }
            return ks;
    
        }
    
        /**
         * 通过PFX文件获得别名
         *
         * @param  //文件路径
         * @param //PFX密码
         * @return 别名
         */
        public static String getAlsformPfx(String strPfx, String strPassword)
                throws Exception {
            String keyAlias = null;
            KeyStore ks = getKsformPfx(strPfx, strPassword);
            Enumeration<String> enumas = ks.aliases();
            keyAlias = null;
            // we are readin just one certificate.
            if (enumas.hasMoreElements()) {
                keyAlias = (String) enumas.nextElement();
            }
            return keyAlias;
        }
    
        /**
         * 获取公钥
         */
        public static PublicKey getPubKeyFromCRT(String crtFileName) throws Exception {
            InputStream is = new FileInputStream(crtFileName);
            CertificateFactory cf = CertificateFactory.getInstance("x509");
            Certificate cerCert = cf.generateCertificate(is);
            return cerCert.getPublicKey();
        }
    
        /**
         * 加密方法 source: 源数据
         */
        public static String encrypt(String source, String publicKey)
                throws Exception {
            Key key = getPublicKey(publicKey);
            /** 得到Cipher对象来实现对源数据的RSA加密 */
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] b = source.getBytes();
            /** 执行加密操作 */
            byte[] b1 = cipher.doFinal(b);
            return new String(Base64.encodeBase64(b1),
                    CHAR_ENCODING);
        }
        /**
         * 加密方法 source: 源数据
         */
        public static String encrypt(String source, PublicKey pubKeyFromCrt)
                throws Exception {
            Key key = pubKeyFromCrt;
            /** 得到Cipher对象来实现对源数据的RSA加密 */
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] b = source.getBytes();
            /** 执行加密操作 */
            byte[] b1 = cipher.doFinal(b);
            return new String(Base64.encodeBase64(b1),
                    CHAR_ENCODING);
        }
        /**
         * 解密算法 cryptograph:密文
         */
        public static String decrypt(String cryptograph, PrivateKey privateKey)
                throws Exception {
            Key key = privateKey;
            /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] b1 = Base64.decodeBase64(cryptograph.getBytes());
            /** 执行解密操作 */
            byte[] b = cipher.doFinal(b1);
            return new String(b);
        }
    
        /**
         * 得到公钥
         * 
         * @param key
         *            密钥字符串(经过base64编码)
         * @throws Exception
         */
        public static PublicKey getPublicKey(String key) throws Exception {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(
                    Base64.decodeBase64(key.getBytes()));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        }
    
        /**
         * 得到私钥
         * 
         * @param key
         *            密钥字符串(经过base64编码)
         * @throws Exception
         */
        public static PrivateKey getPrivateKey(String key) throws Exception {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
                    Base64.decodeBase64(key.getBytes()));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        }
    
        /**
         * 签名
         */
        public static String sign(String content, String privateKey) {
            String charset = CHAR_ENCODING;
            try {
                PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
                        Base64.decodeBase64(privateKey.getBytes()));
                KeyFactory keyf = KeyFactory.getInstance("RSA");
                PrivateKey priKey = keyf.generatePrivate(priPKCS8);
    
                Signature signature = Signature.getInstance("SHA1WithRSA");
    
                signature.initSign(priKey);
                signature.update(content.getBytes(charset));
    
                byte[] signed = signature.sign();
    
                return new String(Base64.encodeBase64(signed));
            } catch (Exception e) {
    
            }
    
            return null;
        }
    
        /**
         * 验签
         */
        public static boolean checkSign(String content, String sign, String publicKey)
        {
            try 
            {
                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                byte[] encodedKey = Base64.decode2(publicKey);
                PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    
    
                Signature signature = Signature
                .getInstance("SHA1WithRSA");
    
                signature.initVerify(pubKey);
                signature.update( content.getBytes("utf-8") );
    
                boolean bverify = signature.verify( Base64.decode2(sign) );
                return bverify;
    
            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }
    
            return false;
        }   
        /**
         * 生成RSA签名
         */
        public static String handleRSA(TreeMap<String, Object> map,
                String privateKey) {
            StringBuffer sbuffer = new StringBuffer();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                sbuffer.append(entry.getValue());
            }
            String signTemp = sbuffer.toString();
    
            String sign = "";
            if (StringUtils.isNotEmpty(privateKey)) {
                sign = RSA.sign(signTemp, privateKey);
            }
            return sign;
        }
    
        /**
         * 解密算法 cryptograph:密文
         */
        public static String decrypt(String cryptograph, String privateKey)
                throws Exception {
            Key key = getPrivateKey(privateKey);
            /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] b1 = Base64.decodeBase64(cryptograph.getBytes());
            /** 执行解密操作 */
            byte[] b = cipher.doFinal(b1);
            return new String(b);
        }
    
    }

    测试类:

    package com.alex.util;
    
    import java.util.Map;
    
    public class RSATest {
        public static void main(String[] args) throws Exception {
            String reqStr = "加密证书和RSA加密解密";
            //加密
            Map<String,String>  map = Decipher.encryptData(reqStr);
    
            //解密
            String respStr = Decipher.decryptData(map);
            System.out.println("解密后的数据为=============>" + respStr);
        }
    }

    结果: 
    这里写图片描述

    源码下载:http://download.csdn.net/detail/qq_32347977/9444440

  • 相关阅读:
    [计算机网络-传输层] 无连接传输:UDP
    [BinaryTree] 最大堆的类实现
    [OS] 生产者-消费者问题(有限缓冲问题)
    [剑指Offer] 64.滑动窗口的最大值
    [剑指Offer] 63.数据流中的中位数
    [剑指Offer] 62.二叉搜索树的第k个结点
    [OS] CPU调度
    [剑指Offer] 60.把二叉树打印成多行
    MySQL数据库实验二:单表查询
    数据库实验:基本表的定义与修改
  • 原文地址:https://www.cnblogs.com/lishuiqing/p/7910982.html
Copyright © 2011-2022 走看看