`
mmdev
  • 浏览: 12937987 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

IOS学习十五:通信加密

 
阅读更多

通信加解密基本算是每个涉及到用户信息的客户端都会用到的一个技术。

一般我们可能就做简单的防篡改和密文加密。

很多时候做一个加密只不过是一个小小的心理安慰吧了,因为纯粹的从安全角度来说,安全性真的不高。

对于一些手机支付以及银联的客户端,我看到有用的证书什么来实现。

因为没做过,所以也不是太了解。

这边就说下最简单的加密方案。


一:MD5数字摘要。

准确来说,MD5不能叫做加解密,因为它不可逆性。

一般我们理解的加解密是能加密,然后解密的。

MD5只是根据数据生个一个校验码,然后对于数据接受者接受到内容后同样的在通过md5来生成校验码于之前的校验码对比是否一致,

从而来判断数据在传送过程中是否被截取篡改过。

说白了,其实在传输过程中,仅仅md5技术,数据任然是明文的。

下面我来来看下IOS中对md5加密的支持。

 const char *original_str = [string UTF8String];//string为摘要内容,转成char

  /****系统api~~~~*****/
    unsigned char result[CC_MD5_DIGEST_LENGTH];  
    CC_MD5(original_str, strlen(original_str), result);//调通系统md5加密
    NSMutableString *hash = [[NSMutableString string]autorelease];
    for (int i = 0; i < 16; i++)
        [hash appendFormat:@"%02X", result[i]];
       return hash ;//校验码

代码很简单,因为内部算法都是系统已经完成的。

对于以上来看,仍然没有很好的处理密文传输只是在数据传输过程成做了一个简单的防篡改。

因此需要使用一种能生成密文的安全机制类支持。


二:ios中3DES加密

3DES是一种对称的加密方式,因为用的同一个密钥。

对于加解密的安全性什么大家可以google,baidu自己找资料参考。

我也不过是简单的说一下通信加密中的一种可实现方案而已。

同样的3DES加密基本也都是统一的,系统也直接提供了API,基本代码如下

//3des加解密
+ (NSString*)TripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt
{
    
    const void *vplainText;
    size_t plainTextBufferSize;
    
    if (encryptOrDecrypt == kCCDecrypt)//解密
    {
        NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];
        plainTextBufferSize = [EncryptData length];
        vplainText = [EncryptData bytes];
    }
    else //加密
    {
        NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
        plainTextBufferSize = [data length];
        vplainText = (const void *)[data bytes];
    }
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    // memset((void *) iv, 0x0, (size_t) sizeof(iv));
    
     const void *vkey = (const void *) [DESKEY UTF8String];
   // NSString *initVec = @"init Vec";
    //const void *vinitVec = (const void *) [initVec UTF8String];
   //  Byte iv[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
    ccStatus = CCCrypt(encryptOrDecrypt,
                       kCCAlgorithm3DES,
                        kCCOptionPKCS7Padding | kCCOptionECBMode,
                       vkey, 
                       kCCKeySize3DES,
                       nil, 
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    //if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
    /*else if (ccStatus == kCC ParamError) return @"PARAM ERROR";
     else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";
     else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";
     else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";
     else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";
     else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED"; */
    
    NSString *result;
    
    if (encryptOrDecrypt == kCCDecrypt)
    {
        result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr 
                                                                length:(NSUInteger)movedBytes] 
                                        encoding:NSUTF8StringEncoding] 
                  autorelease];
    }
    else
    {
        NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        result = [GTMBase64 stringByEncodingData:myData];
    }
    
    return result;
这个在网上也能搜索到详细代码。

但是要注意到一点:

CCCrypt(encryptOrDecrypt,
                       kCCAlgorithm3DES,
                        kCCOptionPKCS7Padding | kCCOptionECBMode,
                       vkey, 
                       kCCKeySize3DES,
                       nil, 
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
这个里面的参数可能会根据你服务端使用的对应的3des算法构造时参数的不同而需要自己调整。

比如我在网上看到的这个第三个参数只是用了kCCOptionPKCS7Padding,第六个可选参数用了上面一个自定义的iv。

但是这边根据服务器,这个参数是nil才对应。

这边也附上java端的加解密代码

public String encryptThreeDESECB(String src,String key) throws Exception
	{
	  DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
	  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
	  SecretKey securekey = keyFactory.generateSecret(dks);
	  
	  Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
	  cipher.init(Cipher.ENCRYPT_MODE, securekey);
	  byte[] b=cipher.doFinal(src.getBytes());
	  
	  BASE64Encoder encoder = new BASE64Encoder();
	  return encoder.encode(b).replaceAll("\r", "").replaceAll("\n", "");
	  
	}

	//3DESECB解密,key必须是长度大于等于 3*8 = 24 位
	public String decryptThreeDESECB(String src,String key) throws Exception
	{
	  //--通过base64,将字符串转成byte数组
	  BASE64Decoder decoder = new BASE64Decoder();
	  byte[] bytesrc = decoder.decodeBuffer(src);
	  //--解密的key
	  DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
	  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
	  SecretKey securekey = keyFactory.generateSecret(dks);
	  
	  //--Chipher对象解密
	  Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");  
	  cipher.init(Cipher.DECRYPT_MODE, securekey);  
	  byte[] retByte = cipher.doFinal(bytesrc);  
	        
	  return new String(retByte);
	}

内容也很少,这这么点。

然后是key,也就是共用密钥的客户端和服务端都保存一个。

简单从数据传输来说,密文传输了,安全性相对来说提高了不少。

但是如果破解了客户端代码,那么其实密钥也就暴露了。

这对于android上面来说,因为反编译额纯在,安全性不敢恭维,

ios的貌似好一点,因为暂未听说反编译ios的app的。


以上就是一种简单的通信加密方案。

当然,其实这些其实算是通用技术~


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics