AES-128-CBC Base64 Encryption--oc,java,golang interlock

Source: Internet
Author: User
Tags pkcs5 pkcs7


Aes-128-cbc



First of all, here's the AES encryption principle.
The AES encryption algorithm uses the block cipher system, each packet data length is 128 bits 16 bytes, the key length can be 128 bits 16 bytes, 192 bit or 256 bits, a total of four kinds of encryption mode (ECB, CBC, CFB, OFB), we usually use the CBC mode which needs the initial vector IV , the length of the initial vector is defined as 128 bits and 16 bytes. The other is padding, there is a big hole in it .... Let's talk about the three modes of padding PKCS5, PKCS7 and nopadding. PKCS5 is the absence of several bytes of packet data, the number of bytes that are populated at the end of the data, such as the absence of 5 bytes, and the padding of 5 bytes at the end of 5. PKCS7 refers to the absence of several bytes of packet data, which fills a few bytes of 0 at the end of the data, such as missing 7 bytes, padding 7 bytes at the end of 0. Nopadding means that no padding is required, which means that the sender of the data will certainly ensure that the last piece of data is exactly 16 bytes. The PKCS5, if it is exactly 16 bytes and the last 16, will be padded with 16 16 to differentiate, and PKC7 to fill 16 0 for 0 o'clock. And in the OC method of iOS does not provide PKCS5, only PKCS7 more pit is true docking when found on iOS PKCS7 and other end PKCS5 is the same .... So it is now the idea to share a step on the pit, specific what reason I am afraid only Apple home know, system method is really pit! Java can be directly completed by the system method to set the end of the battle ... Go words padding this piece of writing to implement other systems can be set. Finally say the key length only iOS is to set its own number of bits and then corresponding bits write key, the other platform directly corresponding to the number of write key can, so it is best to each platform in the package to determine the length of the key, the size of the incident vector, otherwise the end of the corresponding or to be foolish.



Base64



Here is a Base64, this is also a pit, iOS system provides base64 optional type is not commonly used in known areas, normal padding and websafe,padding will fill =, and Websafe will replace "+" for "-", "\" for "_"
and iOS provides the below, completely infrequently used ...


NSDataBase64Encoding64CharacterLineLength Its function is to divide the generated Base64 string into 64-character lengths.
NSDataBase64Encoding76CharacterLineLength Its function is to divide the generated Base64 string into six lines of characters.
NSDataBase64EncodingEndLineWithCarriageReturn Its purpose is to end the generated Base64 string with a carriage return.
NSDataBase64EncodingEndLineWithLineFeed Its purpose is to end the generated Base64 string with a newline.


Basically GTMBase64 with a fixed, and then also to expand the padding settings, the original only Websafe mode open the padding settings, the internal actually has the corresponding logic only need to add a method to call it. Here are the two ways to add and micro-change


+(NSString *)stringByEncodingData:(NSData *)data padded:(BOOL)padded{
    NSString *result = nil;
    NSData *converted = [self baseEncode:[data bytes]
                                  length:[data length]
                                 charset:kBase64EncodeChars
                                  padded:padded];
    if (converted) {
        result = [[[NSString alloc] initWithData:converted
                                        encoding:NSUTF8StringEncoding] autorelease];
    }
    return result;
}
+(NSData *)decodeString:(NSString *)string {
    NSData *result = nil;
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    if (data) {
        result = [self baseDecode:[data bytes]
                           length:[data length]
                          charset:kBase64DecodeChars
                   requirePadding:NO];
    }
    return result;
}


As for java,android development is very cool directly with the android.util.base64, which can be directly set nopadding and Websafe, and pure Java with java.util.base64 will write their own replacement logic, the specific code see the source part
Finally, the go Direct system approach provides the perfect solution


base64.StdEncoding
base64.URLEncoding websafe mode
base64.RawStdEncoding nopadding
base64.RawURLEncoding websafe mode nopadding


AES-128-CBC +base64-nopadding Source



The following is the 3 language to implement AES-128-CBC +base64-nopadding, from the coding experience and the corresponding obvious Java clearest, go to write something for themselves, OC is even on the response and normal understanding of the scope of deviation.



Oc


#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCryptor.h>

@interface NSData (Encryption)

- (NSData *) AES128EncryptWithKey:(NSString *)key Iv:(NSString *)Iv; //Encryption
- (NSData *) AES128DecryptWithKey: (NSString *) key Iv: (NSString *) Iv; / / decrypt

@end

@implementation NSData (Encryption)

//(key and iv vectors are 16 bits here) Here is the CBC encryption mode, which is more secure

- (NSData *) AES128EncryptWithKey:(NSString *)key Iv:(NSString *)Iv{//Encryption
    // 'key' should be 32 bytes for AES128, will be null-padded otherwise
    Char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
    Bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
    
    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    
    Char ivPtr[kCCKeySizeAES128+1];
    Memset(ivPtr, 0, sizeof(ivPtr));
    [Iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];
    
    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    Size_t bufferSize = dataLength + kCCBlockSizeAES128;
    Void *buffer = malloc(bufferSize);
    
    Size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES128,
                                          ivPtr /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          Buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
    If (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        Return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    
    Free(buffer); //free the buffer;
    Return nil;
}


- (NSData *) AES128DecryptWithKey:(NSString *)key Iv:(NSString *)Iv{//decrypt
    Char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
    Bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
    
    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    Char ivPtr[kCCKeySizeAES128+1];
    Memset(ivPtr, 0, sizeof(ivPtr));
    [Iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];
    
    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    Size_t bufferSize = dataLength + kCCBlockSizeAES128;
    Void *buffer = malloc(bufferSize);
    
    Size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES128,
                                          ivPtr /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          Buffer, bufferSize, /* output */
                                          &numBytesDecrypted);
    
    If (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        Return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }
    
    Free(buffer); //free the buffer;
    Return nil;
}

@end

@interface SecurityCore
+ (NSString*)encryptAESString:(NSString*)string;
+ (NSString*)decryptAESString:(NSString*)string;
@end

@implementation SecurityCore

#pragma mark - AES encryption
Const NSString * skey=@"dde4b1f8a9e6b814"
Const NSString * ivParameter =@"dde4b1f8a9e6b814"

/ / Convert string to data with password
+(NSString*)encryptAESString:(NSString*)string
{
    / / Convert nsstring to nsdata
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    / / Use cipher to encrypt nsdata
    NSData *encryptedData = [data AES128EncryptWithKey:skey Iv:ivParameter];
    NSString *encryptedString=[GTMBase64 stringByEncodingData:encryptedData padded:NO];
    
    Return encryptedString;
}

+ (NSString*)decryptAESString:(NSString*)string{
    
    
    / / Convert nsstring to nsdata
    NSData *data = [GTMBase64 decodeString:string];

    NSData *decryptData = [data AES128DecryptWithKey:skey Iv:ivParameter];

    NSString *str = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
    Return [str autorelease];
}

@end


Java


Import javax.crypto.Cipher;
Import javax.crypto.spec.IvParameterSpec;
Import javax.crypto.spec.SecretKeySpec;

Import java.util.Base64;


Public class SecurityCore {
    /*
     * Key for encryption can be composed of 26 letters and numbers. The AES-128-CBC encryption mode is used here, and the key needs to be 16 bits.
     */
    Private String sKey = "dde4b1f8a9e6b814";
    Private String ivParameter = "dde4b1f8a9e6b814";
    Private static SecurityCore instance = null;

    Private SecurityCore() {

    }

    Public static SecurityCore getInstance() {
        If (instance == null)
            Instance = new SecurityCore();
        Return instance;
    }

    Public static String webSafeBase64StringEncoding(byte[] sSrc,boolean padded) throws Exception {
        String encodeString=Base64.getEncoder().encodeToString(sSrc);// Here BASE64 is used for transcoding.

        //websafe base64
        encodeString=encodeString.replace("+","-");
        encodeString=encodeString.replace("/","_");

        //nopadding base64
        If (!padded) {
            If (encodeString.endsWith("=")) {
                encodeString = encodeString.substring(0, encodeString.length() - 1);
                If (encodeString.endsWith("=")) {
                    encodeString = encodeString.substring(0, encodeString.length() - 1);
                }
            }
        }
        Return encodeString;
    }

    Public static byte[] webSafeBase64StringDecoding(String sSrc) throws Exception {
        //websafe base64
        sSrc=sSrc.replace("-","+");
        sSrc=sSrc.replace("_","/");

        Return Base64.getDecoder().decode(sSrc);
    }

    Public static String base64StringEncoding(byte[] sSrc,boolean padded) throws Exception {
        String encodeString=Base64.getEncoder().encodeToString(sSrc);// Here BASE64 is used for transcoding.

        //nopadding base64
        If (!padded) {
            If (encodeString.endsWith("=")) {
                encodeString = encodeString.substring(0, encodeString.length() - 1);
                If (encodeString.endsWith("=")) {
                    encodeString = encodeString.substring(0, encodeString.length() - 1);
                }
            }
        }
        Return encodeString;
    }

    Public static byte[] base64StringDecoding(String sSrc) throws Exception {
        Return Base64.getDecoder().decode(sSrc);
    }

    Public static byte[] AES128CBCStringEncoding(String encData ,String secretKey,String vector) throws Exception {

        If(secretKey == null) {
            Return null;
        }
        If(secretKey.length() != 16) {
            Return null;
        }
        If (vector != null && vector.length() != 16) {
            Return null;
        }
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        Byte[] raw = secretKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// Using CBC mode, a vector iv is needed to increase the strength of the encryption algorithm.
        Cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        Byte[] encrypted = cipher.doFinal(encData.getBytes("utf-8"));

        Return encrypted;
    }

    Public static String AES128CBCStringDecoding(byte[] sSrc,String key,String ivs) throws Exception {
        Try {
            If(key == null) {
                Return null;
            }
            If(key.length() != 16) {
                Return null;
            }
            If (ivs != null && ivs.length() != 16) {
                Return null;
            }
            Byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivs.getBytes());
            Cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            Byte[] original = cipher.doFinal(sSrc);
            String originalString = new String(original, "utf-8");
            Return originalString;
        } catch (Exception ex) {
            Return null;
        }
    }


    // encryption
    Public String encrypt(String sSrc) throws Exception {
        Try {
            String encodeString=base64StringEncoding(AES128CBCStringEncoding(sSrc,sKey,ivParameter),false);

            Return encodeString;
        } catch (Exception ex) {
            Return null;
        }
    }

    // decrypt
    Public String decrypt(String sSrc) throws Exception {
        Try {
            String decodeString=AES128CBCStringDecoding(base64StringDecoding(sSrc),sKey,ivParameter);
            Return decodeString;
        } catch (Exception ex) {
            Return null;
        }
    }

    //test
    Public static void main(String[] args) throws Exception {
        // string that needs to be encrypted
        String cSrc = "123";

        // encryption
        Long lStart = System.currentTimeMillis();
        String enString = SecurityCore.getInstance().encrypt(cSrc);
        System.out.println("The encrypted string is: " + enString);

        Long lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("Encryption Time:" + lUseTime + "Milliseconds");
        // decrypt
        lStart = System.currentTimeMillis();
         String DeString = SecurityCore.getInstance().decrypt(enString);
         System.out.println("The decrypted string is: " + DeString);
         lUseTime = System.currentTimeMillis() - lStart;
         System.out.println("decryption time:" + lUseTime + "milliseconds");
     }
}


Golang


Package main
Import(
    "fmt"
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "bytes"
)

Const (
    sKey = "dde4b1f8a9e6b814"
    ivParameter = "dde4b1f8a9e6b814"
)

/encryption
Func PswEncrypt(src string)(string){
    Key := []byte(sKey)
    Iv := []byte(ivParameter)

    Result, err := Aes128Encrypt([]byte(src), key, iv)
    If err != nil {
        Panic(err)
    }
    Return base64.RawStdEncoding.EncodeToString(result)
}
//decrypt
Func PswDecrypt(src string)(string) {

    Key := []byte(sKey)
    Iv := []byte(ivParameter)

    Var result []byte
    Var err error

    Result,err=base64.RawStdEncoding.DecodeString(src)
    If err != nil {
        Panic(err)
    }
    origData, err := Aes128Decrypt(result, key, iv)
    If err != nil {
        Panic(err)
    }
    Return string(origData)

}
Func Aes128Encrypt(origData, key []byte, IV []byte) ([]byte, error) {
    If key == nil || len(key) != 16 {
        Return nil, nil
    }
    If IV != nil && len(IV) != 16 {
        Return nil, nil
    }

    Block, err := aes.NewCipher(key)
    If err != nil {
        Return nil, err
    }
    blockSize := block.BlockSize()
    origData = PKCS5Padding(origData, blockSize)
    blockMode := cipher.NewCBCEncrypter(block, IV[:blockSize])
    Crypted := make([]byte, len(origData))
    / / According to the description of the CryptBlocks method, the initialization of crypted can also be
    blockMode.CryptBlocks(crypted, origData)
    Return crypted, nil
}

Func Aes128Decrypt(crypted, key []byte,IV []byte) ([]byte, error) {
    If key == nil || len(key) != 16 {
        Return nil, nil
    }
    If IV != nil && len(IV) != 16 {
        Return nil, nil
    }

    Block, err := aes.NewCipher(key)
    If err != nil {
        Return nil, err
    }
    blockSize := block.BlockSize()
    blockMode := cipher.NewCBCDecrypter(block,IV[:blockSize])
    origData := make([]byte, len(crypted))
    blockMode.CryptBlocks(origData, crypted)
    origData = PKCS5UnPadding(origData)
    Return origData, nil
}

Func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    Padding := blockSize - len(ciphertext)%blockSize
    Padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    Return append(ciphertext, padtext...)
}

Func PKCS5UnPadding(origData []byte) []byte {
    Length := len(origData)
    // remove the last byte unpadding times
    Unpadding := int(origData[length-1])
    Return origData[:(length - unpadding)]
}

Func main(){
    encodingString := PswEncrypt("123")
    decodingString := PswDecrypt(encodingString);
    fmt.Printf("AES-128-CBC\n encryption: %s\n decryption: %s\n", encodingString, decodingString)
}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.