三种常见的加密技术:3DES、SHA1、MD5。其中3DES和SHA1为对称加密,MD5为非对称加密。
加密我们可以做的加密措施有哪些?
对设备中存储的内容进行加密,开发者经常使用的UserDefaults、plist文件、CoreData框架等作为存储数据的载体,在存入数据之前做一些加密以增强数据的安全性是很有必要的。对网络传输的数据进行加密,大部分的引用都需要进行网络通讯,由于网络传输的过程中的一些中间节点并不可控,所以必然存在着数据泄漏的风险,对敏感信息进行加密以保证用户的隐私权是很有必要的。对账户密码进行加密:加盐(salt)在密码学中是指,通过密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这个过程称之为加盐。加盐后的账户密码再经过诸如MD5等方式加密,然后与服务器采用同样的加盐和加密的密码进行比较,若两个密码相同,则密码匹配成功。这样无论在客户端还是服务器端,当传输的密码被截获后,即便是解密成功,也无法还原出原始的密码。 3DES加密DES数据加密标准。
3DES三重数据加密算法,即对每个数据块应用三次DES加密算法。
由于随着计算机的发展,计算机的算力有了很大的提升,而3DES通过增加DES的密钥长度来避免破解,而不是设计一种全新的块密码算法。
在swift中使用3DES函数需要 import CommonCrypto。
private let randomStringArray:[Character] = "abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".map({$0})
var key:String = ""
func randomStringOfLength(length:Int) -> String {
var string = ""
for _ in 1...length {
string.append(randomStringArray[Int(arc4random_uniform(UInt32(randomStringArray.count)-1))])
}
print("randomStringLength:\(length)")
print("randomStringArray:\(randomStringArray)")
print("randomString:\(string)")
return string
}
func encrypt(encryptData:String) -> () {
//从key参数到bytesDecrypted参数,都是为了生成CCCrypt方法参数的值。
key = randomStringOfLength(length: 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(kCCEncrypt), 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("加密过程出错")
}
}
代码解释:CCCrypt参数准备
从key参数到bytesDecrypted参数,都是为了生成CCCrypt方法参数的值。
key = randomStringOfLength(length: kCCKeySize3DES)
上述代码,通过randomStringOfLength方法生成一个随机字符串作为3DES加解密的Key值,其中kCCKeySize3DES是指Triple DES 加解密的Key的大小,其值为24,因此这里将生成一个长度为24的、包含英文大小写字母和数字的随机字符串。
let inputData:Data = encryptData.data(using: String.Encoding.utf8)!
上述代码,将待加密的字符串转换为Data类型。
let keydata:Data = key.data(using: String.Encoding.utf8,allowLossyConversion: false)!
上述代码,将作为随机字符串的key值同样转换为Data类型。
let keyBytes = UnsafeMutableRawPointer(mutating: (keydata as NSData).bytes)
上述代码,将创建一个UnsafeMutableRawPointer指针。在Swift中,指针都是用一个特殊的类型来表示的,这个特殊的类型是UnsafeRawPointer。相对应的,同样有一个特殊的类型是UnsafeMutableRawPointer。在创建该指针时,向系统申请了个数为(keydata as NSData).bytes的UInt8泛型类型的内存。
let keyLength = size_t(kCCKeySize3DES)
上述代码,创建了一个名为keyLength的常量,使用size_t方法取出kCCKeySize3DES的长度。因为kCCKeySize3DES已知长度是24,所以keyLength的值就是24。
let datalength = Int(inputData.count)
上述代码,获得待加密对象inputData的长度
let dataBytes = UnsafeRawPointer((inputData as NSData).bytes)
上述代码,创建了一个UnsafeRawPointer指针,并从系统中分配相应的内存作为加密的 input buffer。
let bufferData = NSMutableData(length: Int(datalength)+kCCBlockSize3DES)!
上述代码,创建了一个指定长度的NSMutableData可变的二进制数据对象,该对象将作为加密的 output buffer,用来存储加密后的数据。其长度是 input buffer 的长度和 3DES 加密的kCCBlockSize3DES块大小之和,kCCBlockSize3DES块的大小是8。
let bufferPointer = UnsafeMutableRawPointer(bufferData.mutableBytes)
上述代码,创建一个UnsafeMutableRawPointer类型的指针,并根据 output buffer,也就是bufferData的大小分配相应的内存。
let bufferLength = size_t(bufferData.length)
var bytesDecrypted = Int(0)
上述代码,获得 output buffer 的长度。并创建了一个变量bytesDecrypted,用于存储加密后的 output buffer 的最终字节数。
代码解释:CCCrypt方法执行在所有的参数都准备好了之后就可以调用CommonCrypto框架中的CCCrypt方法了。
let cryptStatus = CCCrypt(
UInt32(kCCEncrypt),
UInt32(kCCEncrypt), UInt32(kCCOptionECBMode+kCCOptionPKCS7Padding),
keyBytes,
keyLength,
nil,
dataBytes,
datalength,
bufferPointer,
bufferLength,
&bytesDecrypted)
CCCrypt方法中的第一个参数表示进行加密 *** 作还是解密 *** 作,kCCEncrypt表示的是加密 *** 作。
第二个参数表示进行加密的算法,在CommonCrypto框架中提供了:
kCCAlgorithmAESkCCAlgorithmAES128kCCAlgorithmDESkCCAlgorithm3DESkCCAlgorithmCASTkCCAlgorithmRC4kCCAlgorithmBlowfish等多种加密算法。
第三个参数用来设置 block ciphers 的选项, block ciphers 表示在使用密钥和算法对文本进行加密的方法。该选项可以是kCCOptionPKCS7Padding或者kCCOptionECBMode两者其中之一。如果使用PKCS7Padding,它的密钥可以是8个字节,也可以不是。
判断CCCrypt执行的结果当执行完CCCrypt方法后,会返回一个cryptStatus状态,通过cryptStatus能判断是否加密成功。
CCCrypt方法的cryptStatus的几种状态:
if Int32(cryptStatus)==Int32(kCCSuccess) {
bufferData.length = bytesDecrypted
decrypt(inputData: bufferData as Data)
}else{
print("加密过程出错")
}
当判断加密 *** 作完成后,设置output data 的length为 bytesDecrypted,以调整输出的buffer的大小为最终输出加密数据的尺寸。
至此就完成了数据的加密 *** 作。
然后我们编辑ViewDidLoad案例,让其运行起来尝试一下加密。
override func viewDidLoad() {
super.viewDidLoad()
print("kCCBufferTooSmall:\(kCCBufferTooSmall)")
print("kCCAlignmentError:\(kCCAlignmentError)")
print("kCCDecodeError:\(kCCDecodeError)")
let string1 = "todayPerfect"
encrypt(encryptData: string1)
let string2 = "today is a good day"
encrypt(encryptData: string2)
}
运行结果:
kCCBufferTooSmall:-4301
kCCAlignmentError:-4303
kCCDecodeError:-4304
todayPerfect加密后:{length = 16, bytes = 0xc09e74b86d0fa97fd6bb1831eba14c96}
加密过程出错 error: -4301
由此可知,string2"today is a good day"在加密的过程中出错了,通过其打印的反馈可知,因为选项中设置的缓存大小不够,所以调整一下缓存大小即可。
let bufferLength = size_t(bufferData.length)*2
运行结果:
kCCBufferTooSmall:-4301
kCCAlignmentError:-4303
kCCDecodeError:-4304
todayPerfect加密后:{length = 16, bytes = 0xcae3ed8d4ca2dbbaa41bf8957de39bae}
today is a good day加密后:{length = 32, bytes = 0xbf45b7f9 265d93bd 22cb08b1 c1eac78e ... 875f1f00 00000000 }
加密成功了,从打印信息可以看到string1的长度是16,而string2的长度是32.至此解决了参数设置中因缓存不足而导致加密失败的问题。
解密对密文进行解密 *** 作,接着使用相同的密钥对密文进行解密 *** 作。
3DES不会解密😓💦有时候可以有时候又不行真是伤脑筋
SHA1加密SHA1是安全哈希算法。在swift中使用SHA1加密函数需要 import CommonCrypto。
对于长度小于2的64次方位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用于检验消息的完整性。
SHA1的特性是,并不能从消息摘要中复原信息,并且不同的信息会有不同的消息摘要。
代码:
extension Int {
//将整型数据转换为字符类型,且是16进制的
func hexedString()->String {
return NSString(format: "%02x", self) as String
}
}
extension NSData {
//将2进制的数据转换为字符类型,且为16进制
func hexedString()->String {
var string = String()
//bytes是NSData对象属性,此处将UnsafeRawPointer类型的bytes转换为UnsafePointer类型
let unsafePointer = bytes.assumingMemoryBound(to: UInt8.self)
for i in UnsafeBufferPointer<UInt8>(start: unsafePointer, count: length) {
string += Int(i).hexedString()
}
return string
}
//对数据进行SHA1加密的拓展方法
func SHA1()->NSData{
//创建一个长度为CC_SHA1_DIGEST_LENGTH的一个可变数据对象。
let result = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH))!
let unsafePoint = result.mutableBytes.assumingMemoryBound(to: UInt8.self)
//CC_SHA1加密方法,
CC_SHA1(bytes, CC_LONG(length), UnsafeMutablePointer<UInt8>(unsafePoint))
return NSData(data: result as Data)
}
}
extension String{
//对字符串进行加密的拓展方法
func SHA1()->String{
//使用utf-8的编码格式将字符串转化为NSData对象。
let data = (self as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
//再调用自己刚拓展的加密方法。
return data.SHA1().hexedString()
}
}
调用:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let string = "乐事派"
print("加密结果:"+string.SHA1())
print("密文长度:\(string.SHA1().lengthOfBytes(using: String.Encoding.utf8))")
}
运行结果:
加密结果:a7482271d4b63e594c75cbf739c76c6c35016a0d
密文长度:40
MD5 加密
MD5的全称是Message Digest Algorithm 5,也就是消息摘要算法第五版。是一种散列函数,以提供消息的完整性保护。
MD5可以将任意长度的字符串变成一个长度为128bit的大整数,并且是一个不可逆的字符串变换算法。也就是说无法回溯为原来的具体信息。
MD5经常被用在验证一段数据是否被篡改。
代码:基本与SHA1的加密过程类似。
extension Int {
//将整型数据转换为字符类型,且是16进制的
func hexedString()->String {
return NSString(format: "%02x", self) as String
}
}
extension NSData {
//将2进制的数据转换为字符类型,且为16进制
func hexedString()->String {
var string = String()
//bytes是NSData对象属性
let unsafePointer = bytes.assumingMemoryBound(to: UInt8.self)
for i in UnsafeBufferPointer<UInt8>(start: unsafePointer, count: length) {
string += Int(i).hexedString()
}
return string
}
func MD5()->NSData{
let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))!
let unsafePoint = result.mutableBytes.assumingMemoryBound(to: UInt8.self)
CC_MD5(bytes, CC_LONG(length), UnsafeMutablePointer<UInt8>(unsafePoint))
return NSData(data: result as Data)
}
}
extension String{
func MD5()->String{
let data = (self as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
return data.MD5().hexedString()
}
}
验证代码:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let string = "乐事派"
print("加密结果:"+string.MD5())
print("密文长度:\(string.MD5().lengthOfBytes(using: String.Encoding.utf8))")
}
运行结果:
加密结果:2f0ef9512a21f5739d58680e4932c6ac
密文长度:32
越狱情况的判定:
数据在传输过程中安全很重要,但数据在本地存储上的安全同样也很重要,虽然苹果系统是封闭的,但是也仍有可破解的方法,这个方式就是越狱苹果手机。
越狱后的苹果手机由于没有了沙盒的保护,黑客可以对其中的内容进行修改,因此在内购支付的过程中,苹果返回的已付款凭证就有可能是伪造的。因此我们在这方面还需要做一下苹果手机是否已经越狱的判断。
苹果设备的越狱是通过Cydia来实现的。因此可以通过判断是否有相关的文件夹或程序来判断是否处于越狱。
通常越狱的文件、软件特征有以下:
Cydia.applimera 1 n.appgreenpois0n.appblacksn0n.appredsn0w.appAbsinthe.app代码:
func isBroken()->Bool{
let apps = ["Applications/Cydia.app",
"Applications/limera 1 n.app",
"Applications/greenpois0n.app",
"Applications/blacksn0n.app",
"Applications/redsn0w.app",
"Applications/Absinthe.app",]
for appPath in apps {
if (FileManager.default.fileExists(atPath: appPath)) {
return true
}
}
}
验证:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if isBroken() {
print("您的设备已经过越狱,请留意支付安全")
}else{
//没有越狱则无需提醒用户
print("无越狱")
}
}
运行结果:
无越狱
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)