• Swift


    前段时间有个网友问是否有Swift的HMAC_SHA1算法。这次就专门写篇相关文章进行介绍。要说明HMAC-SHA1,首先要先了解什么是HMAC,什么是SHA。 

    1,HMAC(散列消息身份验证码:Hashed Message Authentication Code)
    它不是散列函数,而是采用了将MD5或SHA1散列函数与共享机密密钥(与公钥/私钥对不同)一起使用的消息身份验证机制。基本来说,消息与密钥组合并运行散列函数。然后运行结果与密钥组合并再次运行散列函数。这个128位的结果被截断成96位,成为MAC。

    hmac主要应用在身份验证中,它的使用方法是这样的:
    1. 客户端发出登录请求(假设是浏览器的GET请求)
    2. 服务器返回一个随机值,并在会话中记录这个随机值
    3. 客户端将该随机值作为密钥,用户密码进行hmac运算,然后提交给服务器
    4. 服务器读取用户数据库中的用户密码和步骤2中发送的随机值做与客户端一样的hmac运算,然后与用户发送的结果比较,如果结果一致则验证用户合法

    在这个过程中,可能遭到安全攻击的是服务器发送的随机值和用户发送的hmac结果,而对于截获了这两个值的黑客而言这两个值是没有意义的,绝无 获取用户密码的可能性,随机值的引入使hmac只在当前会话中有效,大大增强了安全性和实用性。大多数的语言都实现了hmac算法,比如php的 mhash、python的hmac.py、java的MessageDigest类,在web验证中使用hmac也是可行的,用js进行md5运算的速 度也是比较快的。

    2,SHA(安全散列算法:Secure Hash Algorithm)
    这个是美国国家标准和技术局发布的国家标准FIPS PUB 180-1,一般称为SHA-1。其对长度不超过264二进制位的消息产生160位的消息摘要输出,按512比特块处理其输入。
    SHA是一种数据加密算法,该算法经过加密专家多年来的发展和改进已日益完善,现在已成为公认的最安全的散列算法之一,并被广泛使用。该算法的 思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度 较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说时对明文的一种“指纹”或是“摘要”所以对散列值的数字签名 就可以视为对此明文的数字签名。

    3,HMAC_SHA1(Hashed Message Authentication Code, Secure Hash Algorithm)
    这是一种安全的基于加密hash函数和共享密钥的消息认证协议。它可以有效地防止数据在传输过程中被截获和篡改,维护了数据的完整性、可靠性和安全性。HMAC_SHA1消息认证机制的成功在于一个加密的hash函数、一个加密的随机密钥和一个安全的密钥交换机制。
    HMAC_SHA1算法在身份验证和数据完整性方面可以得到很好的应用,在目前网络安全也得到较好的实现。

    4,下面演示如何使用Swift进行HMAC_SHA1计算
    (1)首先创建桥接头文件bridge.h来包含需要引用的Objective-C头文件,并在项目中配置
    1
    #import <CommonCrypto/CommonHMAC.h>

    (2)下面是一个封装类,同时对String进行HMAC扩展。(除了SHA1,还可以使用其它算法比如MD5,SHA224等)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    //HMAC.swift
    import Foundation
    enum CryptoAlgorithm {
        case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
         
        var HMACAlgorithm: CCHmacAlgorithm {
            var result: Int = 0
            switch self {
            case .MD5:      result = kCCHmacAlgMD5
            case .SHA1:     result = kCCHmacAlgSHA1
            case .SHA224:   result = kCCHmacAlgSHA224
            case .SHA256:   result = kCCHmacAlgSHA256
            case .SHA384:   result = kCCHmacAlgSHA384
            case .SHA512:   result = kCCHmacAlgSHA512
            }
            return CCHmacAlgorithm(result)
        }
         
        var digestLength: Int {
            var result: Int32 = 0
            switch self {
            case .MD5:      result = CC_MD5_DIGEST_LENGTH
            case .SHA1:     result = CC_SHA1_DIGEST_LENGTH
            case .SHA224:   result = CC_SHA224_DIGEST_LENGTH
            case .SHA256:   result = CC_SHA256_DIGEST_LENGTH
            case .SHA384:   result = CC_SHA384_DIGEST_LENGTH
            case .SHA512:   result = CC_SHA512_DIGEST_LENGTH
            }
            return Int(result)
        }
    }
     
    extension String {
        func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
            let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
            let strLen = Int(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
            let digestLen = algorithm.digestLength
            let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
            let keyStr = key.cStringUsingEncoding(NSUTF8StringEncoding)
            let keyLen = Int(key.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
             
            CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
             
            let digest = stringFromResult(result, length: digestLen)
             
            result.dealloc(digestLen)
             
            return digest
        }
         
        private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
            let hash = NSMutableString()
            for i in 0..<length {
                hash.appendFormat("%02x", result[i])
            }
            return String(hash)
        }
    }

    (3)测试样例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let str = "welcome to hangge.com"
    let key = "67FG"
    let hmacStr = str.hmac(.SHA1, key: key)
             
    print("原始字符串:(str)")
    print("key:(key)")
    print("HMAC运算结果:(hmacStr)")
             
    /**** 输出 ******
    原始字符串:welcome to hangge.com
    key:67FG
    HMAC运算结果:79a5f5b138b5646289a9648de035c80e9c5c14c7
    *****/

    原文出自:www.hangge.com  转载请保留原文链接:http://www.hangge.com/blog/cache/detail_851.html
  • 相关阅读:
    “连城决”——预示2008年手机营销体式格式新打破
    都会演出连城诀—诺基亚N78决战入手入手了!
    Lyx:阔别单调的 LaTeX 节制命令
    [转载]Oracle 11g R1下的自动内存经管(2)
    假造化手艺是决胜企业IT化的关头
    请各位博友对HyperV的运用终了指摘
    有199元的Office,还要用盗版吗?
    十一回南通,当晚和同学去小石桥附近的网吧
    Windows 消息
    WinAPI: 钩子回调函数之 MsgFilterProc
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4858361.html
Copyright © 2020-2023  润新知