DES(Data EncryptionStandard)又叫数据加密标准,是1973年5月15日美国国家标准局(现在是美国标准技术研究所,即NIST)在联邦记录中公开征集密码体制时出现的。DES加密算法是一种对称加密技术,该算法的要求主要为以下四点:

  • 提供高质量的数据保护,防止数据未经授权的泄露和未被察觉的修改;
  • 具有较高的复杂性,使得破译的开销超过可能获得的利益,同时又要便于理解和掌握;
  • 密码体制的安全性应该不依赖于算法的保密,其安全性仅以加密密钥的保密为基础;
  • 实现经济,运行有效,并且适用于多种完全不同的应用。

而3DES(或称为TripleDES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

创建项目并建立桥接文件

接着我们来创建一个示例项目,对一个字符串进行3DES加密和解密。首先创建一个基于[Single View Applicaton]模板的空白项目,然后在左侧的项目名称文件夹上点击鼠标右键,并选择右键菜单中的[New File...]选项,创建一个桥接头文件,这是因为我们需要使用到Object-C的CommonCrypto。
在弹出的模板选择窗口中,依次选择[Source > Header File]选项,以创建一个.h的头文件,如图1所示:


图 1

桥接头文件创建完成后,打开并编辑该文件,以引入相关的头文件,如图2所示:


图 2

接着还需要在Build Settings面板中设置Objective-C Bridging Header,在进入Build Settings面板之后,在搜索输入框内输入objective-c bridging进行搜索,以定位Objective-C Bridging Header选项,并设置该选项的值为桥接文件所在的位置,如图3所示:


图 3


实现3DES加解密功能

完成项目的配置之后,在左侧的项目导航区打开并编辑[ViewController.swift]文件,开始3DES加解密功能的实现。在该文件中首先创建一个集合,用来生成随机的公用key值:

private let randomStringArray: [Character] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMnopQRSTUVWXYZ0123456789".characters.map({$0})


接着给ViewController类添加一个名为key的字符串属性,作为3DES加密的公钥和私钥,并对其进行初始化操作:
var key:String = ""


然后添加一个名为randomStringOfLength方法,用来获得指定长度的随机字符串,该字符串从randomStringArray集合中获得英文大小写字母和0至9之间的数字,然后由这些字符通过一个for–in 循环组成指定长度的随机字符串。其中uniform方法可以用来产生0~(n-1)范围内的随机数,不需要再进行取模运算。如果要生成1至n的随机数,可以这么写:arc4random_uniform(n)+1:

func randomStringOfLength(_ length:Int) -> String {
	var string = ""
	 for _ in (1...length) {
		string.append(randomStringArray[Int(arc4random_uniform(
	                                 UInt32(randomStringArray.count) - 1))])
	}
	 return string
}

然后添加一个名为encrypt方法,对字符串参数encryptData进行加密:

func encrypt(encryptData:String){
    key = randomStringOfLength(kCCKeySize3DES)
    let inputData : Data = encryptData.data(using: String.Encoding.utf8)!

    let keyData: Data = key.data(using: String.Encoding.utf8,allowLossyConversion: false)!
    let keyBytes = UnsafeMutableRawPointer(mutating: (keyData as NSData).bytes)
    let keyLength = size_t(kCCKeySize3DES)

    let dataLength = Int(inputData.count)
    let dataBytes = UnsafeRawPointer((inputData as NSData).bytes)
    let bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)!
    let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes)
    let bufferLength = size_t(bufferData.length)
    var bytesDecrypted = Int(0)
        
    let cryptStatus = CCCrypt(
        UInt32(kCCEncrypt),UInt32(kCCAlgorithm3DES),UInt32(kCcoptionECBMode + kCcoptionPKCS7Padding),keyBytes,keyLength,nil,dataBytes,dataLength,bufferPointer,bufferLength,&bytesDecrypted)

        if Int32(cryptStatus) == Int32(kCCSuccess) {
            bufferData.length = bytesDecrypted
            decrypt(inputData: bufferData as Data) 
        } else {
            print("加密过程出错: \(cryptStatus)")
        }
    }


CCCrypt参数的配置

在该方法中的第2行至14行的代码,都是用来生成CCCrypt方法中的各种参数的值。

首先在第2行的代码中,通过randomStringOfLength方法,生成一个随机字符串作为3DES加解密的key值。其中kCCKeySize3DES是指Triple DES加解密的key的大小,其值为24,因此这里将生成一个长度为24的包含英文大小写字母和数字的随机字符串。

接着在第3行的代码中,将待加密的字符串转换为Data类型。

在第5行的代码中,将作为随机字符串的key值同样转换为Data类型。

在第6行的代码中,创建一个UnsafeMutableRawPointer指针。在 Swift 中,指针都使用一个特殊的类型来表示,那就是UnsafeRawPointer。对应地它还有一个可变变体, UnsafeMutableRawPointer 。在创建该指针时,向系统申请了个数为(keyData as NSData).bytes的UInt8泛型类型的内存。

在第7行的代码中,创建一个名为keyLength的常量,表示key值的长度。根据kCCKeySize3DES的大小可以得知,keyLenght的值为24。

然后在第9行的代码中,获得待加密的Data类型对象的长度。并在第20行的代码中,创建一个UnsafePointer指针,并从系统中分配相应的内存作为加密的input buffer。

在第11行的代码中,创建一个指定长度的NSMutableData可变的二进制数据对象,该对象将作为加密的outputbuffer,用来存储加密后的数据。其长度为input buffer的长度和3DES加密的kCCBlockSize3DES块大小之和,kCCBlockSize3DES块的大小为8。

接着在第12行的代码中,创建一个UnsafeMutablePointer类型的指针,并根据output buffer即bufferData的大小分配相应的内存。

然后在第13行的代码中,获得outputbuffer的长度。最后在第14行的代码中,创建一个变量bytesDecrypted,用来存储加密后的output buffer的最终字节数。

执行CCCrypt方法

完成所有的参数设置之后,在第16至27行的代码中,调用CommonCryptor.h中的CCCrypt方法对数据进行加密操作。

其中CCCrypt方法的第一个参数表示进行加密操作,还是进行解密操作,这里使用kCCEncrypt表示进行加密操作。

第二个参数表示进行加密的算法,在CommonCryptor.h中提供了kCCAlgorithmAES128、kCCAlgorithmAES、kCCAlgorithmDES、kCCAlgorithm3DES、kCCAlgorithmCAST、kCCAlgorithmRC4、kCCAlgorithmRC2、kCCAlgorithmBlowfish等多种类型的加密算法。

第三个参数用来设置block ciphers(block cipher表示在使用密钥和算法对文本进行加密时的方法)的选项,该选项可以是kCcoptionPKCS7Padding或kCcoptionECBMode两者中的任一个。假如使用PKCS7Padding,它的密钥可以是8个字节,也可以不是。

CCCrypt方法的其它几个参数就是我们在第2行至14行号配置好的参数。

判断CCCrypt方法执行的结果

当执行完CCCrypt方法后,会返回一个cryptStatus状态,通过cryptStatus判断是否加密成功。其中kCCSuccess表示加密成功,除此之外还有其它几种状态,如表1所示:

表1 CCCrypt结果状态列表

状态值

说明

kCCSuccess

加解密操作正常结束。

kCCParamError

非法的参数值。

kCCBufferTooSmall

选项设置的缓存不够大。

kCcmemoryFailure

内存分配失败。

kCCAlignmentError

输入大小匹配不正确。

kCCDecodeError

输入数据没有正确解码或解密。

kCCUnimplemented

函数没有正确执行当前的算法。

当判断加密操作正确完成后,设置output data的length为bytesDecrypted,以调整输出buffer的大小为最终输出加密数据的尺寸。

对密文进行解密操作

至此就完成了数据的加密操作,接着使用相同的密钥对密文进行解密操作。该功能通过调用decrypt方法来实现:

func decrypt(inputData : Data){
    let keyData: Data = key.data(using: String.Encoding.utf8,allowLossyConversion: false)!
    let keyBytes = UnsafeMutableRawPointer(mutating: (keyData as NSData).bytes)
    let keyLength = size_t(kCCKeySize3DES)
    let dataLength = Int(inputData.count)
    let dataBytes = UnsafeRawPointer((inputData as NSData).bytes)
    let bufferData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)!
    let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes)
    let bufferLength = size_t(bufferData.length)
    var bytesDecrypted = Int(0)
        
    let cryptStatus = CCCrypt(
        UInt32(kCCDecrypt),&bytesDecrypted) 

        if Int32(cryptStatus) == Int32(kCCSuccess) {
            bufferData.length = bytesDecrypted 
            let clearDataAsstring = Nsstring(data: bufferData as Data,encoding: String.Encoding.utf8.rawValue)
            print("解密后的内容:\(clearDataAsstring as! String)")
        } else {
            print("解密过程出错: \(cryptStatus)")
        }
}

解密的方法与加密的方法大体相似,需要注意不同的地方是,在第13行使用kCCDecrypt进行解密运算。然后在72行的代码中,将解密后的数据转换为Nsstring对象,并通过print语句在日志区进行打印输出。

修改viewDidLoad方法

最后一步是修改ViewController类的viewDidLoad方法,在该方法中调用加密方法encrypt,对明文coolketang.com进行加密操作:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view,typically from a nib.
        
    encrypt(encryptData: "coolketang.com");
}

现在已经完成了所有的加解密的编码工作,点击Xcode界面左上角的[编译并运行]按钮 ,打开模拟器运行项目。项目运行后,将弹出一个空白的模拟器,并在日志区输出解密后的结果,如图4所示:


图 4





新 作

iOS开发中的神兵利器

共140节课程,讲解GitHub中近百个过千star的iOS热门开源项目
市面上唯一大规模讲解GitHub中热门的iOS开源项目的教程
快速、优雅地解决iOS开发工作中遇到的各种棘手问题

视频观看地址:http://study.163.com/course/courseMain.htm?courseId=1003657013

互动教程下载地址:https://itunes.apple.com/cn/app/id1209739676


使用Swift 3.0实现原生的3DES加密和解密的更多相关文章

  1. ios – 从Swift重写一个Obj-C类方法,返回NSArray

    .要在Swift子类中指定可选或具体值,请使用Objective-Cnullability说明符:exampleMethod;桥接以覆盖类funcexampleMethod()–>[AnyObject]exampleMethod;桥接以覆盖类funcexampleMethod()–>[AnyObject]?exampleMethod;和exampleMethod;具有相同的行为并桥接到隐式解包的可选项.

  2. 开始使用 swift 的 c语言 库

    为了手头上的一个项目,我需要使用CommonCrypto库中的HMAC函数.虽然苹果在swift中已经提供了许多系统库,但是CommonCrypto不在其中.庆幸的是,要使用这个库并不怎么费事,只需要做一点额外的工作.开始访问库在使用库之前,我们需要通知Swift编译器.要完成这个过程,我们有两种方式.它们都能在示例工程中正常运行,但是你应该根据你代码的用途来选择具体的方式.好消息是,你随便使用那

  3. Swift 与 Object-C 交互 Swift版本为:1.2

    一个是Swift项目调用Object-C的类,另一个是Object-C项目调用Swift类。我们的结构目录变成这样,我这里新建的桥接文件名为“SwiftCallObject-C-Bridging-Header.h”。如果你是第在Object-C项目里第一次创建Swift的类,那么依旧会有窗口提示,询问你是否需要创建桥接文件。这里先说明一下,在Object-C中调用Swift时,Xcode会帮助我们自动生成头文件,不需要我们去维护。谨记,在Object-C调用Swift端代码时,Swift类的class前需

  4. Swift和OC混用

    记得去年在北京一家公司的时候就使用了swift和OC混编。在这里想写一下swift和OC混用的一些简单使用方法,如果有错误请批评指正.在一个应用的target中导入一些Objective-C文件供Swift代码使用时,你需要依赖于Objective-C的桥接头文件来暴露给Swift。当你添加Swift文件到现有的Objective-C应用(或反之)时,Xcode会自动创建这些头文件。在这个桥接头文件中列出的所有public的Objective-C头文件都会对Swift可见。用Swift语法使用这些Obje

  5. swift开发

    [myTableViewinsertSubview:mySubviewatIndex:2在Swift中如下调用。在Objective-C中的指针在导入Swift时被映射为Swift语言的optional类型。importUIKitclassMySwiftViewControllerUIViewController{//definetheclass}如下定义了一个采用Objective-C中的UITableViewDelegate和UITableViewDataSource协议的Swift类MySwiftV

  6. Swift和OC文件间的相互调用

    公共文件/桥接的方法2016/1/2613:33Swift使用OC文件方法看完上面内容之后,你只需要这么做,swift就能使用OC的类了注意这里是搜索bridging注意这里是搜索bridgingOC使用Swift文件方法在你需要使用的文件中导入头文件#import"-Swift.h"如果不行,创建一个桥接文件就行,桥接文件内不写任何代码.Xcode路径要填#

  7. swift 与oc 混编

    生成一个桥接文件Swift_Objc-Bridging-Header.h,这个文件在swift调用oc时学要用到。在viewController,中引入Swift_Objc-Swift.h文件,即可用oc语言使用swift类ViewController.h文件中调用代码:swift调用oc:在Swift_Objc-Bridging-Header.h文件中引入.h头文件,即可用swift语言调用oc类。

  8. oc 和swift 混编之--准备工作

    之前的一段时间在学习swift,觉得可以出师了,哈哈哈,遂打算把oc和swift混编起来,混起来才发现远远比想象的要复杂。因为当前正在做的项目是用oc写的,也不打算用swift重新写一遍,所以直接在当前项目里加入swift代码,这当然是允许的,不过在此之前要做一些准备工作。也很简单,在你需要使用的那个类里边,import这样一个文件“项目名-Swift.h”:8E2FD4C0-4DF2-4A1B-BB66-9F0D43E5BF35.png这样oc就可以访问swift了。

  9. Swift与OC混合使用

    Swift中调用OC文件如果你是在原有的Swift项目中创建OC文件,那么Xcode将自动进行提示,询问你是否要建立一个桥接,然后选择是。如果是在Swift中引入一个OC文件的话,而之前你项目中又不存在这个桥接文件,那么你就要手动创建一个。OC文件调用Swift如果你的OC文件或者项目中需要用的Swift中的类,但是Swift中又不提供头文件怎么办,没关系,只需要在OC文件中引入”项目名-Swift.h“,即可成功调用。,如下图

  10. swift oc 双语言混编 持续更新

    过分依赖IDE带来的后果,就是一旦出现问题,根本就摸不清头脑,找不到根源!d.桥文件出现了,注意它目前的位置,是在Target包里,而不是在项目包里面!f.最后,在我们的.h桥接文件中,import想要在swift中用到的OC类就行了,大功告成!

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部