资讯专栏INFORMATION COLUMN

AES128位,CBC模式加解密

JinB / 3115人阅读

摘要:使用原因因为在项目中,需要在与客户端交互的时候,保存一些私有信息,不被别人看到,所以,使用了比较流行的可以反向加解密的。

使用原因:

因为在项目中,需要在与客户端(IOS,Android)交互的时候,保存一些私有信息,不被别人看到,所以,使用了比较流行的可以反向加解密的AES。

PHP 源码
aes128cbcEncrypt("11122222");
echo "
";
echo $aes->aes128cbcEncrypt("中文aes演示");
echo "
";
class aes{
    const KEY="625202f9149e061d";
    const IV ="5efd3f6060e20330";
    /**
     * pkcs7补码
     * @param string $string  明文
     * @param int $blocksize Blocksize , 以 byte 为单位
     * @return String
     */ 
    private function addPkcs7Padding($string, $blocksize = 32) {
        $len = strlen($string); //取得字符串长度
        $pad = $blocksize - ($len % $blocksize); //取得补码的长度
        $string .= str_repeat(chr($pad), $pad); //用ASCII码为补码长度的字符, 补足最后一段
        return $string;
    }

    /**
     * 加密然后base64转码
     * 
     * @param String 明文
     * @param 加密的初始向量(IV的长度必须和Blocksize一样, 且加密和解密一定要用相同的IV)
     * @param $key 密钥
     */
    function aes256cbcEncrypt($str, $iv, $key ) {   
        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $this->addPkcs7Padding($str) , MCRYPT_MODE_CBC, $iv));
    }

    /**
     * 除去pkcs7 padding
     * 
     * @param String 解密后的结果
     * 
     * @return String
     */
    private function stripPkcs7Padding($string){
        $slast = ord(substr($string, -1));
        $slastc = chr($slast);
        $pcheck = substr($string, -$slast);

        if(preg_match("/$slastc{".$slast."}/", $string)){
            $string = substr($string, 0, strlen($string)-$slast);
            return $string;
        } else {
            return false;
        }
    }
    /**
     * 解密
     * 
     * @param String $encryptedText 二进制的密文 
     * @param String $iv 加密时候的IV
     * @param String $key 密钥
     * @return String
     */
    function aes256cbcDecrypt($encryptedText, $iv, $key) {
        $encryptedText =base64_decode($encryptedText);
        return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encryptedText, MCRYPT_MODE_CBC, $iv));
    }

    function aes128cbcDecrypt($encryptedText, $iv=self::IV, $key=self::KEY) {
        $encryptedText =base64_decode($encryptedText);
        return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encryptedText, MCRYPT_MODE_CBC, $iv));
    }

    function hexToStr($hex)//十六进制转字符串
    {   
        $string=""; 
        for($i=0;$ihexToStr($encryptedText);
        return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC, $iv));
    }

    function aes128cbcEncrypt($str, $iv=self::IV, $key=self::KEY ) {    // $this->addPkcs7Padding($str,16)
        $base = (mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$this->addPkcs7Padding($str,16) , MCRYPT_MODE_CBC, $iv));
        return $this->strToHex($base);
    }
}
运行结果

在线验证加解密结果

验证地址
http://www.seacha.com/tools/aes.html

IOS 源码
@implementation NSString (AES256)
-(NSString *) aes256_encrypt:(NSString *)key
{
    const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:self.length];
    //对数据进行加密
    NSData *result = [data aes256_encrypt:key];

    //转换为2进制字符串
    if (result && result.length > 0) {

        Byte *datas = (Byte*)[result bytes];
        NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
        for(int i = 0; i < result.length; i++){
            [output appendFormat:@"%02x", datas[i]];
        }
        return output;
    }
    return nil;
}

-(NSString *) aes256_decrypt:(NSString *)key
{
    //转换为2进制Data
    NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
    unsigned char whole_byte;
    char byte_chars[3] = {"","",""};
    int i;
    for (i=0; i < [self length] / 2; i++) {
        byte_chars[0] = [self characterAtIndex:i*2];
        byte_chars[1] = [self characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [data appendBytes:&whole_byte length:1];
    }

    //对数据进行解密
    NSData* result = [data aes256_decrypt:key];
    if (result && result.length > 0) {
        return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
    }
    return nil;
}
@end





@implementation NSData (AES256)

- (NSData *)aes256_encrypt:(NSString *)key   //加密
{
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding ,
                                          keyPtr, kCCBlockSizeAES128,
                                          [AES_IV UTF8String],
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}

- (NSData *)aes256_decrypt:(NSString *)key   //解密
{
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding ,
                                          keyPtr, kCCBlockSizeAES128,
                                          [AES_IV UTF8String],
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];

    }
    free(buffer);
    return nil;
}

@end
Android
javaimport java.io.UnsupportedEncodingException;

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

/**
 * AES加密解密算法
 * 
 * @author long
 */
public class AesEncryptionUtil {
    // /** 算法/模式/填充 **/
    private static final String CipherMode = "AES/CBC/PKCS5Padding";

    // /** 创建密钥 **/
    private static SecretKeySpec createKey(String key) {
        byte[] data = null;
        if (key == null) {
            key = "";
        }
        StringBuffer sb = new StringBuffer(16);
        sb.append(key);
        while (sb.length() < 16) {
            sb.append("0");
        }
        if (sb.length() > 16) {
            sb.setLength(16);
        }

        try {
            data = sb.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new SecretKeySpec(data, "AES");
    }

    private static IvParameterSpec createIV(String password) {
        byte[] data = null;
        if (password == null) {
            password = "";
        }
        StringBuffer sb = new StringBuffer(16);
        sb.append(password);
        while (sb.length() < 16) {
            sb.append("0");
        }
        if (sb.length() > 16) {
            sb.setLength(16);
        }

        try {
            data = sb.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new IvParameterSpec(data);
    }

    // /** 加密字节数据 **/
    public static byte[] encrypt(byte[] content, String password, String iv) {
        try {
            SecretKeySpec key = createKey(password);
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.ENCRYPT_MODE, key, createIV(iv));
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // /** 加密(结果为16进制字符串) **/
    public static String encrypt(String content, String password, String iv) {
        byte[] data = null;
        try {
            data = content.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        data = encrypt(data, password, iv);
        String result = ToHexUtil.byte2hex(data);
        return result;
    }

    // /** 解密字节数组 **/
    public static byte[] decrypt(byte[] content, String password, String iv) {
        try {
            SecretKeySpec key = createKey(password);
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.DECRYPT_MODE, key, createIV(iv));
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // /** 解密 **/
    public static String decrypt(String content, String password, String iv) {
        byte[] data = null;
        try {
            data = ToHexUtil.hex2byte(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        data = decrypt(data, password, iv);
        if (data == null)
            return null;
        String result = null;
        try {
            result = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30262.html

相关文章

  • java解密实例

    摘要:序本文主要小结一下里头的以及加解密。属于块加密,块加密中有等几种工作模式。与一样在加密前需要对数据进行填充,不是很适合对流数据进行加密。 序 本文主要小结一下java里头的AES以及RSA加解密。 AES showImg(https://segmentfault.com/img/remote/1460000011156406);使用AES加密时需要几个参数: 密钥长度(Key Size...

    mengera88 评论0 收藏0
  • 【JAVA】AES密 简单实现 AES-128/ECB/PKCS5Padding

    摘要:加密是一种可逆加密算法,对用户的敏感信息加密处理。加密错误返回获取加密密文字节数组对密文字节数组进行转换为输出密文返回输出密文加密错误返回解密密文,带解密的内容密码,解密的密码返回明文,解密后得到的内容。 AES加密 AES 是一种可逆加密算法,对用户的敏感信息加密处理。 本文暂不深入AES原理,仅关注JAVA代码实现AES加解密。 JAVA代码实现 在用JAVA实现AES加密前,先浏...

    sourcenode 评论0 收藏0
  • 循序渐进学

    摘要:在古典加密算法当中,加密算法和密钥都是不能公开的,一旦泄露就有被破解的风险,我们可以用词频推算等方法获知明文。年美国公司研制的算法是人类历史上第一个公开加密算法但不公开密钥的加密方法,后来成为美国军方和政府机构的标准加密算法。 还记得上初二的那年夏天,班里来了一个新同学,他就住在我家对面的楼里,于是我们一起上学放学,很快便成了最要好的朋友。我们决定发明一套神秘的沟通方式,任何人看到都不...

    Y3G 评论0 收藏0
  • 循序渐进学

    摘要:在古典加密算法当中,加密算法和密钥都是不能公开的,一旦泄露就有被破解的风险,我们可以用词频推算等方法获知明文。年美国公司研制的算法是人类历史上第一个公开加密算法但不公开密钥的加密方法,后来成为美国军方和政府机构的标准加密算法。 还记得上初二的那年夏天,班里来了一个新同学,他就住在我家对面的楼里,于是我们一起上学放学,很快便成了最要好的朋友。我们决定发明一套神秘的沟通方式,任何人看到都不...

    fsmStudy 评论0 收藏0

发表评论

0条评论

JinB

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<