iOS develops 3ES encryption and decryption corresponding to OC and java

Keywords: Java Android encoding Mobile

The most tangled issue in mobile development is the inconsistency of encryption and decryption between Java, Android and the iPhone platforms. Because the backend of mobile phone is usually a Web Service developed with JAVA, Android and the iPhone client call the same Web Service interface. For data security, data should be encrypted. The headache is coming. It's hard to write an encryption program. The results of encryption and decryption are consistent among the three platforms. You can't write a Web Service interface for Android and iPhone clients, can you? I believe that many friends will be confused about this. Here we share a set of 3D ES encryption program, which can achieve the same encryption and decryption on three platforms: Java, Android and the iPhone.



The first is the JAVA-side encryption tool class, which is also applicable to the Android-side. Without any modification, it can ensure that the encryption and decryption of Java and Android-side are consistent, and Chinese will not be scrambled.

package org.liuyq.des3;
import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

/**
* 3DES Encryption Tool Class
*/
public class Des3 {
// Key
private final static String secretKey = "liuyunqiang@lx100#365#";
// Vector
private final static String iv = "01234567";
// Uniform Encoding Method for Encryption and Decryption
private final static String encoding = "utf-8";

/**
 * 3DES encryption
 * 
 * @param plainText Ordinary text
 * @return
 * @throws Exception 
 */
public static String encode(String plainText) throws Exception {
    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);

    Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
    IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
    cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
    byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding));
    return Base64.encode(encryptData);
}

/**
 * 3DES Decrypt
 * 
 * @param encryptText encrypted text
 * @return
 * @throws Exception
 */
public static String decode(String encryptText) throws Exception {
    Key deskey = null;
    DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
    deskey = keyfactory.generateSecret(spec);
    Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
    IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
    cipher.init(Cipher.DECRYPT_MODE, deskey, ips);

    byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));

    return new String(decryptData, encoding);
}
}




Base64 is used in the encryption tool class above. The source code of this class is as follows:

 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
* Base64 Coding Tool Class
*/
public class Base64 {
private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

public static String encode(byte[] data) {
    int start = 0;
    int len = data.length;
    StringBuffer buf = new StringBuffer(data.length * 3 / 2);

    int end = len - 3;
    int i = start;
    int n = 0;

    while (i <= end) {
        int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff);

        buf.append(legalChars[(d >> 18) & 63]);
        buf.append(legalChars[(d >> 12) & 63]);
        buf.append(legalChars[(d >> 6) & 63]);
        buf.append(legalChars[d & 63]);

        i += 3;

        if (n++ >= 14) {
            n = 0;
            buf.append(" ");
        }
    }

    if (i == start + len - 2) {
        int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8);

        buf.append(legalChars[(d >> 18) & 63]);
        buf.append(legalChars[(d >> 12) & 63]);
        buf.append(legalChars[(d >> 6) & 63]);
        buf.append("=");
    } else if (i == start + len - 1) {
        int d = (((int) data[i]) & 0x0ff) << 16;

        buf.append(legalChars[(d >> 18) & 63]);
        buf.append(legalChars[(d >> 12) & 63]);
        buf.append("==");
    }

    return buf.toString();
}

private static int decode(char c) {
    if (c >= 'A' && c <= 'Z')
        return ((int) c) - 65;
    else if (c >= 'a' && c <= 'z')
        return ((int) c) - 97 + 26;
    else if (c >= '0' && c <= '9')
        return ((int) c) - 48 + 26 + 26;
    else
        switch (c) {
        case '+':
            return 62;
        case '/':
            return 63;
        case '=':
            return 0;
        default:
            throw new RuntimeException("unexpected code: " + c);
        }
}

/**
 * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned.
 */

public static byte[] decode(String s) {

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        decode(s, bos);
    } catch (IOException e) {
        throw new RuntimeException();
    }
    byte[] decodedBytes = bos.toByteArray();
    try {
        bos.close();
        bos = null;
    } catch (IOException ex) {
        System.err.println("Error while decoding BASE64: " + ex.toString());
    }
    return decodedBytes;
}

private static void decode(String s, OutputStream os) throws IOException {
    int i = 0;

    int len = s.length();

    while (true) {
        while (i < len && s.charAt(i) <= ' ')
            i++;

        if (i == len)
            break;

        int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3)));

        os.write((tri >> 16) & 255);
        if (s.charAt(i + 2) == '=')
            break;
        os.write((tri >> 8) & 255);
        if (s.charAt(i + 3) == '=')
            break;
        os.write(tri & 255);

        i += 4;
    }
}
}




Next is the encryption program on the iPhone side, of course, the 3D ES encryption program written in Ojbective-C. The source code is as follows:

 
//
// DES3Util.h
//

import <Foundation/Foundation.h>

@interface DES3Util : NSObject {

}

// Encryption Method
+ (NSString*)encrypt:(NSString*)plainText;

// Decryption method
+ (NSString*)decrypt:(NSString*)encryptText;

@end





 
//
// DES3Util.m
//

import "DES3Util.h" #import <CommonCrypto/CommonCryptor.h> #import "GTMBase64.h" #define gkey @"liuyunqiang@lx100#365#" #define gIv @"01234567"

@implementation DES3Util

// Encryption Method
+ (NSString*)encrypt:(NSString*)plainText {
NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
size_t plainTextBufferSize = [data length];
const void vplainText = (const void )[data bytes];

CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;

bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) &amp; ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);

const void *vkey = (const void *) [gkey UTF8String];
const void *vinitVec = (const void *) [gIv UTF8String];

ccStatus = CCCrypt(kCCEncrypt,
                   kCCAlgorithm3DES,
                   kCCOptionPKCS7Padding,
                   vkey,
                   kCCKeySize3DES,
                   vinitVec,
                   vplainText,
                   plainTextBufferSize,
                   (void *)bufferPtr,
                   bufferPtrSize,
                   &amp;movedBytes);

NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
NSString *result = [GTMBase64 stringByEncodingData:myData];
return result;
} // Decryption method + (NSString*)decrypt:(NSString*)encryptText { NSData *encryptData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]]; size_t plainTextBufferSize = [encryptData length]; const void *vplainText = [encryptData bytes];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;

bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) &amp; ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);

const void *vkey = (const void *) [gkey UTF8String];
const void *vinitVec = (const void *) [gIv UTF8String];

ccStatus = CCCrypt(kCCDecrypt,
                   kCCAlgorithm3DES,
                   kCCOptionPKCS7Padding,
                   vkey,
                   kCCKeySize3DES,
                   vinitVec,
                   vplainText,
                   plainTextBufferSize,
                   (void *)bufferPtr,
                   bufferPtrSize,
                   &amp;movedBytes);

NSString *result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr 
                            length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease];
return result;
} @end




"GTMBase64.h" is introduced into the encryption tool class of the iPhone. This is the Base64 encoding tool class of the iOS platform. It is not necessary to post relevant codes here. You can find them in Baidu as soon as you need them.



In this way, the problem of inconsistent encryption between JAVA, Android and the iPhone can be solved. In fact, there is a better way to solve this problem, that is, to write an encryption program in C language, so that C program can be directly used in iOS platform, while the encryption method written in C language can be invoked in Java and Android through JNI, so that the same encryption program can be invoked in three platforms.

Posted by daedlus on Sun, 07 Jul 2019 11:34:34 -0700