background

In order to improve the security of the project, we generally encrypt the interface transmission, so in the encryption process, we generally use symmetric encryption and asymmetric encryption. Symmetric encryption as long as the two sides have the same secret key can be completed JIA, decryption; Asymmetric encryption requires public and private keys for authentication. The latter is safer than the former. Considering that the transmission security level of the project is not too high, symmetric encryption is selected. However, there is a problem: Android and Java back-end encryption can be consistent, but the ciphertext encrypted on IOS cannot be cracked on Java back-end. Therefore, unified encryption encoding and unified encryption format are required.

1. The android side

(1) Create the AESUtils utility class

public class AESUtils { private static final BASE64Encoder B64_EC = new BASE64Encoder(); private static final BASE64Decoder B64_DC = new BASE64Decoder(); private static final String AES = "AES"; / * * * note: CRYPT_KEY must be 16, if changed to 32 bits or higher position will be submitted to the Java security. InvalidKeyException. Jar and us_export_policy. jar. Copy them to \jre\lib\security under JAVA_HOME. * Download address: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html */ private static final String CRYPT_KEY = "ABC123,"; private static final String IV_STRING = "ABC123,"; /** * encrypt * @param Content Encrypt content * @return ciphertext * @throws Exception e */ public static String encrypt(String content) { byte[] encryptedBytes = new byte[0]; try { byte[] byteContent = content.getBytes("UTF-8"); Byte [] enCodeFormat = crypt_key.getBytes (); byte[] enCodeFormat = crypt_key.getBytes (); SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, AES); byte[] initParam = IV_STRING.getBytes(); IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam); // Specify the encryption algorithm, working mode, and filling mode. Cipher Cipher = cipher.getInstance ("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); encryptedBytes = cipher.doFinal(byteContent); }catch(Exception ex){throw new RuntimeException(" failed to encrypt ", ex); } // Special character processing: "=" to! Encode (encryptedBytes). ReplaceAll ("=", "!") ) .replace("+","@"); } /** * Decrypt * @param Content Ciphertext * @return plaintext * @throws Exception e */ public static String Decrypt (String content) {try { byte[] encryptedBytes = B64_DC.decodeBuffer(content.replaceAll("!" , "=") .replace("+","@")); byte[] enCodeFormat = CRYPT_KEY.getBytes(); SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, AES); byte[] initParam = IV_STRING.getBytes(); IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); byte[] result = cipher.doFinal(encryptedBytes); return new String(result, "UTF-8"); }catch(Exception ex){throw new RuntimeException(" decrypt failed ", ex); } } public static void main(String[] args) { String src = "abc123~! @ # $%...... - * () - + = /. {} ABC test "; SRC += "For the server to receive special symbol processing: if \"+\" sign is received as a space in the background, the front and back ends should agree on the special character processing format "; SRC += "* put the ciphertext \"! The \" sign is replaced with the normal encrypted \"+\""; String mw = encrypt(src); System.out.println(" ciphertext: \n" + mw); mw = "M4ULyXAHaairNEAuxc2VwJyN0AeMtndqgiZs08fqA6+ZbkYeODFJCwEpVnqeVXBI33ibrZqzjBTT3Lohb75B8UlKk9k/Ph+emEM1H0/Xkj/Cq/1g35P9sgn dIttA6Irt"; String mmw = decrypt(mw); System.out.println(" plaintext: "+ MMW); System.out.println(src.equals(mmw)); }}Copy the code

Note: Since there is no BASE64Encoder and BASE64Decoder encoding JAR package on Android terminal, the test needs to rewrite BASE64Encoder and BASE64Decoder encoding classes, the code is as follows

(2) Create encoder file and rewrite BASE64Encoder and BASE64Decoder

1.BASE64Decoder
public class BASE64Decoder extends CharacterDecoder {

/** This class has 4 bytes per atom */
protected int bytesPerAtom() {
    return (4);
  }

  /** Any multiple of 4 will do, 72 might be common */
protected int bytesPerLine() {
    return (72);
  }

 /**
 74        * This character array provides the character to value map
 75        * based on RFC1521.
 76        */
    private final static char pem_array[] = {
       //       0   1   2   3   4   5   6   7
                  'A','B','C','D','E','F','G','H', // 0
                'I','J','K','L','M','N','O','P', // 1
              'Q','R','S','T','U','V','W','X', // 2
               'Y','Z','a','b','c','d','e','f', // 3
              'g','h','i','j','k','l','m','n', // 4
             'o','p','q','r','s','t','u','v', // 5
                'w','x','y','z','0','1','2','3', // 6
              '4','5','6','7','8','9','+','/'  // 7
      };

  private final static byte pem_convert_array[] = new byte[256];

  static {
   for (int i = 0; i < 255; i++) {
        pem_convert_array[i] = -1;
    }
     for (int i = 0; i < pem_array.length; i++) {
        pem_convert_array[pem_array[i]] = (byte) i;
   }
   }
 byte decode_buffer[] = new byte[4];
 /**
103        * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
104        */
protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int rem)
   throws java.io.IOException
 {
      int     i;
    byte    a = -1, b = -1, c = -1, d = -1;

   if (rem < 2) {
         throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
     }
      do {
        i = inStream.read();
         if (i == -1) {
            throw new CEStreamExhausted();
            }
      } while (i == '\n' || i == '\r');
      decode_buffer[0] = (byte) i;

   i = readFully(inStream, decode_buffer, 1, rem-1);
   if (i == -1) {
     throw new CEStreamExhausted();
    }

      if (rem > 3 && decode_buffer[3] == '=') {
          rem = 3;
       }
      if (rem > 2 && decode_buffer[2] == '=') {
          rem = 2;
     }
    switch (rem) {
     case 4:
        d = pem_convert_array[decode_buffer[3] & 0xff];
       // NOBREAK
    case 3:
         c = pem_convert_array[decode_buffer[2] & 0xff];
     // NOBREAK
  case 2:
      b = pem_convert_array[decode_buffer[1] & 0xff];
     a = pem_convert_array[decode_buffer[0] & 0xff];
          break;
     }

     switch (rem) {
      case 2:
        outStream.write( (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
        break;
    case 3:
           outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
          outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
          break;
      case 4:
         outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
          outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
       outStream.write( (byte) (((c << 6) & 0xc0) | (d  & 0x3f)) );
     break;
}
    return;
 }
}
Copy the code
2.BASE64Encoder
public class BASE64Encoder extends CharacterEncoder { /** this class encodes three bytes per atom. */ protected int bytesPerAtom() { return (3); } /** * this class encodes 57 bytes per line. This results in a maximum of 57/3 * * 4 or 76 characters per output line. Not counting the line termination. */ protected int bytesPerLine() { return (57); } /** This array maps the characters to their 6 bit values */ private final static char pem_array[] = { // 0 1 2 3 4 5 6  7 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6 '4', '5', '6', '7', '8', '9', '+', '/' / / 7}; /** * encodeAtom - Take three bytes of input and encode it as 4 printable * characters. Note that if the length in len is less than three is encodes * either one or two '=' signs to indicate padding characters. */ protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len) throws IOException { byte a, b, c; if (len == 1) { a = data[offset]; b = 0; c = 0; outStream.write(pem_array[(a >>> 2) & 0x3F]); outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]); outStream.write('='); outStream.write('='); } else if (len == 2) { a = data[offset]; b = data[offset + 1]; c = 0; outStream.write(pem_array[(a >>> 2) & 0x3F]); outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]); outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]); outStream.write('='); } else { a = data[offset]; b = data[offset + 1]; c = data[offset + 2]; outStream.write(pem_array[(a >>> 2) & 0x3F]); outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]); outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]); outStream.write(pem_array[c & 0x3F]); }}}Copy the code
3.CEFormatException
public class CEFormatException extends IOException { public CEFormatException(String s) { super(s); }}Copy the code
4.CEStreamExhausted
public class CEStreamExhausted extends IOException
{

}

Copy the code
5.CharacterDecoder
public abstract class CharacterDecoder { /** Return the number of bytes per atom of decoding */ abstract protected int bytesPerAtom(); /** Return the maximum number of bytes that can be encoded per line */ abstract protected int bytesPerLine(); /** decode the beginning of the buffer, by default this is a NOP. */ protected void decodeBufferPrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } /** decode the buffer suffix, again by default it is a NOP. */ protected void decodeBufferSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } /** * 103 * This method should return, if it knows, the number of bytes 104 * * that will be decoded. Many formats such as uuencoding provide 105 * this * information. By default we return the maximum bytes that 106 * could have * been encoded on the line. 107 */ protected int decodeLinePrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { return (bytesPerLine()); } /** * 113 * This method post processes the line, if there are error detection * 114 * or correction codes in a line, they are generally processed by 115 * * this method. The simplest version of this method looks for the 116 * * (newline)  character. 117 */ protected void decodeLineSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } /** * 121 * This method does an actual decode. It takes the decoded bytes and * 122 * writes them to the OutputStream. The integer <i>l</i> tells the 123 * * method how many bytes are required. This is always <= bytesPerAtom(). * 124 */ protected void decodeAtom(PushbackInputStream aStream, OutputStream bStream, int l) throws IOException { throw new CEStreamExhausted(); } /** * 130 * This method works around the bizarre semantics of * BufferedInputStream's 131 * read method. 132 */ protected int readFully(InputStream in, byte buffer[], int offset, int len) throws IOException { for (int i = 0; i < len; i++) { int q = in.read(); if (q == -1) return ((i == 0) ? -1 : i); buffer[i + offset] = (byte) q; } return len; } /** * 145 * Decode the text from the InputStream and write the decoded 146 * * octets to the OutputStream. This method  runs until the stream 147 * is * exhausted. 148 * @exception CEFormatException An error has occured while * decoding 149 * @exception CEStreamExhausted The input stream is * unexpectedly out of data 150 */ public void decodeBuffer(InputStream aStream, OutputStream bStream) throws IOException { int i; int totalBytes = 0; PushbackInputStream ps = new PushbackInputStream(aStream); decodeBufferPrefix(ps, bStream); while (true) { int length; try { length = decodeLinePrefix(ps, bStream); for (i = 0; (i + bytesPerAtom()) < length; i += bytesPerAtom()) { decodeAtom(ps, bStream, bytesPerAtom()); totalBytes += bytesPerAtom(); } if ((i + bytesPerAtom()) == length) { decodeAtom(ps, bStream, bytesPerAtom()); totalBytes += bytesPerAtom(); } else { decodeAtom(ps, bStream, length - i); totalBytes += (length - i); } decodeLineSuffix(ps, bStream); } catch (CEStreamExhausted e) { break; } } decodeBufferSuffix(ps, bStream); } /** * 182 * Alternate decode interface that takes a String containing the * encoded 183 * buffer and returns a byte array containing the data. 184 * @exception * CEFormatException An error has occured while decoding 185 */ public byte decodeBuffer(String inputString)[] throws IOException { byte inputBuffer[] = new byte[inputString.length()]; ByteArrayInputStream inStream; ByteArrayOutputStream outStream; inputString.getBytes(0, inputString.length(), inputBuffer, 0); inStream = new ByteArrayInputStream(inputBuffer); outStream = new ByteArrayOutputStream(); decodeBuffer(inStream, outStream); return (outStream.toByteArray()); } /** * 199 * Decode the contents of the inputstream into a buffer. 200 */ public byte decodeBuffer(InputStream in)[] throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); decodeBuffer(in, outStream); return (outStream.toByteArray()); } /** * 208 * Decode the contents of the String into a ByteBuffer. 209 */ public ByteBuffer decodeBufferToByteBuffer(String inputString) throws IOException { return ByteBuffer.wrap(decodeBuffer(inputString)); } /** * 216 * Decode the contents of the inputStream into a ByteBuffer. 217 */ public ByteBuffer decodeBufferToByteBuffer(InputStream in) throws IOException { return ByteBuffer.wrap(decodeBuffer(in)); }}Copy the code
6.CharacterEncoder
public abstract class CharacterEncoder
{
   /** Stream that understands "printing" */
   protected PrintStream pStream;

   /** Return the number of bytes per atom of encoding */
   abstract protected int bytesPerAtom();

   /** Return the number of bytes that can be encoded per line */
   abstract protected int bytesPerLine();

   /**
    * 88 * Encode the prefix for the entire buffer. By default is simply 89 *
    * opens the PrintStream for use by the other functions. 90
    */
   protected void encodeBufferPrefix(OutputStream aStream) throws IOException
   {
   	pStream = new PrintStream(aStream);
   }

   /**
    * 96 * Encode the suffix for the entire buffer. 97
    */
   protected void encodeBufferSuffix(OutputStream aStream) throws IOException
   {
   }

   /**
    * 102 * Encode the prefix that starts every output line. 103
    */
   protected void encodeLinePrefix(OutputStream aStream, int aLength)
   		throws IOException
   {
   }

   /**
    * 109 * Encode the suffix that ends every output line. By default 110 *
    * this method just prints a <newline> into the output stream. 111
    */
   protected void encodeLineSuffix(OutputStream aStream) throws IOException
   {
   	pStream.println();
   }

   /** Encode one "atom" of information into characters. */
   abstract protected void encodeAtom(OutputStream aStream, byte someBytes[],
   		int anOffset, int aLength) throws IOException;

   /**
    * 121 * This method works around the bizarre semantics of
    * BufferedInputStream's 122 * read method. 123
    */
   protected int readFully(InputStream in, byte buffer[])
   		throws IOException
   {
   	for (int i = 0; i < buffer.length; i++)
   	{
   		int q = in.read();
   		if (q == -1)
   			return i;
   		buffer[i] = (byte) q;
   	}
   	return buffer.length;
   }

   /**
    * 136 * Encode bytes from the input stream, and write them as text
    * characters 137 * to the output stream. This method will run until it
    * exhausts the 138 * input stream, but does not print the line suffix for a
    * final 139 * line that is shorter than bytesPerLine(). 140
    */
   public void encode(InputStream inStream, OutputStream outStream)
   		throws IOException
   {
   	int j;
   	int numBytes;
   	byte tmpbuffer[] = new byte[bytesPerLine()];

   	encodeBufferPrefix(outStream);

   	while (true)
   	{
   		numBytes = readFully(inStream, tmpbuffer);
   		if (numBytes == 0)
   		{
   			break;
   		}
   		encodeLinePrefix(outStream, numBytes);
   		for (j = 0; j < numBytes; j += bytesPerAtom())
   		{

   			if ((j + bytesPerAtom()) <= numBytes)
   			{
   				encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
   			} else
   			{
   				encodeAtom(outStream, tmpbuffer, j, (numBytes) - j);
   			}
   		}
   		if (numBytes < bytesPerLine())
   		{
   			break;
   		} else
   		{
   			encodeLineSuffix(outStream);
   		}
   	}
   	encodeBufferSuffix(outStream);
   }

   /**
    * 173 * Encode the buffer in <i>aBuffer</i> and write the encoded 174 *
    * result to the OutputStream <i>aStream</i>. 175
    */
   public void encode(byte aBuffer[], OutputStream aStream) throws IOException
   {
   	ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
   	encode(inStream, aStream);
   }

   /**
    * 183 * A 'streamless' version of encode that simply takes a buffer of 184
    * * bytes and returns a string containing the encoded buffer. 185
    */
   public String encode(byte aBuffer[])
   {
   	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
   	ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
   	String retVal = null;
   	try
   	{
   		encode(inStream, outStream);
   		// explicit ascii->unicode conversion
   		retVal = outStream.toString("8859_1");
   	} catch (Exception IOException)
   	{
   		// This should never happen.
   		throw new Error("CharacterEncoder.encode internal error");
   	}
   	return (retVal);
   }

   /**
    * 202 * Return a byte array from the remaining bytes in this ByteBuffer.
    * 203 *
    * <P>
    * 204 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
    * 205 *
    * <P>
    * 206 * To avoid an extra copy, the implementation will attempt to return
    * the 207 * byte array backing the ByteBuffer. If this is not possible, a
    * 208 * new byte array will be created. 209
    */
   private byte[] getBytes(ByteBuffer bb)
   {
   	/*
   	 * This should never return a BufferOverflowException, as we're 213 *
   	 * careful to allocate just the right amount. 214
   	 */
   	byte[] buf = null;

   	/*
   	 * 218 * If it has a usable backing byte buffer, use it. Use only 219 *
   	 * if the array exactly represents the current ByteBuffer. 220
   	 */
   	if (bb.hasArray())
   	{
   		byte[] tmp = bb.array();
   		if ((tmp.length == bb.capacity()) && (tmp.length == bb.remaining()))
   		{
   			buf = tmp;
   			bb.position(bb.limit());
   		}
   	}

   	if (buf == null)
   	{
   		/*
   		 * 232 * This class doesn't have a concept of encode(buf, len, off),
   		 * 233 * so if we have a partial buffer, we must reallocate 234 *
   		 * space. 235
   		 */
   		buf = new byte[bb.remaining()];

   		/*
   		 * 239 * position() automatically updated 240
   		 */
   		bb.get(buf);
   	}

   	return buf;
   }

   /**
    * 248 * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 249 *
    * result to the OutputStream <i>aStream</i>. 250 *
    * <P>
    * 251 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
    * 252
    */
   public void encode(ByteBuffer aBuffer, OutputStream aStream)
   		throws IOException
   {
   	byte[] buf = getBytes(aBuffer);
   	encode(buf, aStream);
   }

   /**
    * 260 * A 'streamless' version of encode that simply takes a ByteBuffer 261
    * * and returns a string containing the encoded buffer. 262 *
    * <P>
    * 263 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
    * 264
    */
   public String encode(ByteBuffer aBuffer)
   {
   	byte[] buf = getBytes(aBuffer);
   	return encode(buf);
   }

   /**
    * 271 * Encode bytes from the input stream, and write them as text
    * characters 272 * to the output stream. This method will run until it
    * exhausts the 273 * input stream. It differs from encode in that it will
    * add the 274 * line at the end of a final line that is shorter than
    * bytesPerLine(). 275
    */
   public void encodeBuffer(InputStream inStream, OutputStream outStream)
   		throws IOException
   {
   	int j;
   	int numBytes;
   	byte tmpbuffer[] = new byte[bytesPerLine()];

   	encodeBufferPrefix(outStream);

   	while (true)
   	{
   		numBytes = readFully(inStream, tmpbuffer);
   		if (numBytes == 0)
   		{
   			break;
   		}
   		encodeLinePrefix(outStream, numBytes);
   		for (j = 0; j < numBytes; j += bytesPerAtom())
   		{
   			if ((j + bytesPerAtom()) <= numBytes)
   			{
   				encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
   			} else
   			{
   				encodeAtom(outStream, tmpbuffer, j, (numBytes) - j);
   			}
   		}
   		encodeLineSuffix(outStream);
   		if (numBytes < bytesPerLine())
   		{
   			break;
   		}
   	}
   	encodeBufferSuffix(outStream);
   }

   /**
    * 306 * Encode the buffer in <i>aBuffer</i> and write the encoded 307 *
    * result to the OutputStream <i>aStream</i>. 308
    */
   public void encodeBuffer(byte aBuffer[], OutputStream aStream)
   		throws IOException
   {
   	ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
   	encodeBuffer(inStream, aStream);
   }

   /**
    * 316 * A 'streamless' version of encode that simply takes a buffer of 317
    * * bytes and returns a string containing the encoded buffer. 318
    */
   public String encodeBuffer(byte aBuffer[])
   {
   	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
   	ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
   	try
   	{
   		encodeBuffer(inStream, outStream);
   	} catch (Exception IOException)
   	{
   		// This should never happen.
   		throw new Error("CharacterEncoder.encodeBuffer internal error");
   	}
   	return (outStream.toString());
   }

   /**
    * 332 * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 333 *
    * result to the OutputStream <i>aStream</i>. 334 *
    * <P>
    * 335 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
    * 336
    */
   public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
   		throws IOException
   {
   	byte[] buf = getBytes(aBuffer);
   	encodeBuffer(buf, aStream);
   }

   /**
    * 344 * A 'streamless' version of encode that simply takes a ByteBuffer 345
    * * and returns a string containing the encoded buffer. 346 *
    * <P>
    * 347 * The ByteBuffer's position will be advanced to ByteBuffer's limit.
    * 348
    */
   public String encodeBuffer(ByteBuffer aBuffer)
   {
   	byte[] buf = getBytes(aBuffer);
   	return encodeBuffer(buf);
   }

}
Copy the code

2. Java back-end

public class AESUtils { private static final BASE64Encoder B64_EC = new BASE64Encoder(); private static final BASE64Decoder B64_DC = new BASE64Decoder(); private static final String AES = "AES"; / * * * note: CRYPT_KEY must be 16, if changed to 32 bits or higher position will be submitted to the Java security. InvalidKeyException. Jar and us_export_policy. jar. Copy them to \jre\lib\security under JAVA_HOME. * Download address: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html */ private static final String CRYPT_KEY = "ABC123,"; private static final String IV_STRING = "ABC123,"; /** * encrypt * @param Content Encrypt content * @return ciphertext * @throws Exception e */ public static String encrypt(String content) { byte[] encryptedBytes = new byte[0]; try { byte[] byteContent = content.getBytes("UTF-8"); Byte [] enCodeFormat = crypt_key.getBytes (); byte[] enCodeFormat = crypt_key.getBytes (); SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, AES); byte[] initParam = IV_STRING.getBytes(); IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam); // Specify the encryption algorithm, working mode, and filling mode. Cipher Cipher = cipher.getInstance ("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); encryptedBytes = cipher.doFinal(byteContent); }catch(Exception ex){throw new RuntimeException(" failed to encrypt ", ex); } // Special character processing: "=" to! Encode (encryptedBytes). ReplaceAll ("=", "!") ) .replace("+","@"); } /** * Decrypt * @param Content Ciphertext * @return plaintext * @throws Exception e */ public static String Decrypt (String content) {try { byte[] encryptedBytes = B64_DC.decodeBuffer(content.replaceAll("!" , "=") .replace("+","@")); byte[] enCodeFormat = CRYPT_KEY.getBytes(); SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, AES); byte[] initParam = IV_STRING.getBytes(); IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); byte[] result = cipher.doFinal(encryptedBytes); return new String(result, "UTF-8"); }catch(Exception ex){throw new RuntimeException(" decrypt failed ", ex); } } public static void main(String[] args) { String src = "abc123~! @ # $%...... - * () - + = /. {} ABC test "; SRC += "For the server to receive special symbol processing: if \"+\" sign is received as a space in the background, the front and back ends should agree on the special character processing format "; SRC += "* put the ciphertext \"! The \" sign is replaced with the normal encrypted \"+\""; String mw = encrypt(src); System.out.println(" ciphertext: \n" + mw); mw = "M4ULyXAHaairNEAuxc2VwJyN0AeMtndqgiZs08fqA6+ZbkYeODFJCwEpVnqeVXBI33ibrZqzjBTT3Lohb75B8UlKk9k/Ph+emEM1H0/Xkj/Cq/1g35P9sgn dIttA6Irt"; String mmw = decrypt(mw); System.out.println(" plaintext: "+ MMW); System.out.println(src.equals(mmw)); }}Copy the code

3. The ios client encryption

// Define an initial vector value. NSString *const kInitVector = @"ABC123,"; NSString *const key= @"ABC123,"; // Determine the key length, select AES-128 here. size_t const kKeySize = kCCKeySizeAES128; /** AES encryption method @param content string to be encrypted @param key key@return string to be encrypted */ + (NSString *)encryptAES:(NSString *)content{ NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger dataLength = contentData.length; // for end '\\0' +1 char keyPtr[kKeySize +1]; memset(keyPtr, 0, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; // Ciphertext length <= plaintext length + BlockSize size_t encryptSize = dataLength + kCCBlockSizeAES128; void *encryptedBytes = malloc(encryptSize); size_t actualOutSize = 0; NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding]; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, // CBC is used by default Then specify PKCS7Padding keyPtr, kKeySize, initVector.bytes, contentData.bytes, dataLength, encryptedBytes, encryptSize, &actualOutSize); If (cryptStatus = = kCCSuccess) {/ / the encrypted data base64 encoding return [[NSData dataWithBytesNoCopy: encryptedBytes length:actualOutSize] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; } free(encryptedBytes); return nil; } /** AES decryption method @param content string to be decrypted @param key key@return decrypted string */ + (NSString *)decryptAES:(NSString *)content{// The base64 String into Data NSData * contentData = [[NSData alloc] initWithBase64EncodedString: content options:NSDataBase64DecodingIgnoreUnknownCharacters]; NSUInteger dataLength = contentData.length; char keyPtr[kKeySize + 1]; memset(keyPtr, 0, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; size_t decryptSize = dataLength + kCCBlockSizeAES128; void *decryptedBytes = malloc(decryptSize); size_t actualOutSize = 0; NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding]; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, keyPtr, kKeySize, initVector.bytes, contentData.bytes, dataLength, decryptedBytes, decryptSize, &actualOutSize); if (cryptStatus == kCCSuccess) { return [[NSString alloc] initWithData:[NSData dataWithBytesNoCopy:decryptedBytes length:actualOutSize] encoding:NSUTF8StringEncoding]; } free(decryptedBytes); return nil; }Copy the code

4. Js

Next is the js code, aes encryption required in js CryptoJS toolkit download.csdn.net/download/ga download address…

<script type="text/javascript" SRC ="./CryptoJS/crypto-js.js"></script> <script CryptoJS.enc.Utf8.parse('ABC123,'); var iv = CryptoJS.enc.Utf8.parse('ABC123,'); Var source = 'string to be encrypted '; var password=CryptoJS.enc.Utf8.parse(source); Console. log(" original string :"+source); Console. log("utf8 after processing :"+password); var encrypted = CryptoJS.AES.encrypt(password, key, { iv: iv,mode:CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}); //CryptoJS.pad.Pkcs7 var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv,mode:CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}); // Cryptojs.pad.pkcs7 console.log(" Base64 :"+encrypted); var encryptedStr=encrypted.ciphertext.toString(); Console. log(" hexadecimal after encryption :"+encryptedStr); Console. log(" utf8:"+decrypted); Console. log(" Decrypted original string :"+ decrypted.tostring (cryptojs.enc.utf8)); </script>Copy the code

4. The last

Thanks to run blogger provide ideas: blog.csdn.net/gao36951/ar…