Swift 使用带有ripemd160 的hash_hmac 散列一个字符串 [英] Swift hash a string using hash_hmac with ripemd160

查看:52
本文介绍了Swift 使用带有ripemd160 的hash_hmac 散列一个字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 ripemd160 在 Swift 3(和/或目标 C)中散列字符串以模拟以下 php 的输出:

I'm trying to hash a String in Swift 3 (and/or objective C) using ripemd160 to emulate the output of the following php:

$string = 'string';
$key = 'test';

hash_hmac('ripemd160', $string, $key);

// outputs: 37241f2513c60ae4d9b3b8d0d30517445f451fa5


到目前为止:

我尝试研究了我能找到的 hash_hmac 功能,例如:
快速实现 HMAC 和 SHA1 加密

I've tried looking into hash_hmac functionality that I can find, such as:
Implementing HMAC and SHA1 encryption in swift

enum HMACAlgorithm {
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512, RIPEMD160

    func toCCHmacAlgorithm() -> 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
        case .RIPEMD160:
            result = kCCHmacAlgRIPEMD160
        }
        return CCHmacAlgorithm(result)
    }

    func digestLength() -> Int {
        var result: CInt = 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: HMACAlgorithm, key: String) -> String {
        let cKey = key.cString(using: String.Encoding.utf8)
        let cData = self.cString(using: String.Encoding.utf8)
        var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digestLength()))
        CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, Int(strlen(cKey!)), cData!, Int(strlen(cData!)), &result)
        let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))
        let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters)
        return String(hmacBase64)
    }
}

并实施:

let hmacResult: String = "myStringToHMAC".hmac(algorithm: HMACAlgorithm.SHA1, key: "foo")

这使我能够使用 hmac 和 <CommonCrypto/CommonHMAC.h>

This enables me to successfully hash a string using hmac and one of the encryption algorithms provided by <CommonCrypto/CommonHMAC.h>

问题

问题是该库不提供对 ripemd160 的支持,那么我如何添加这种支持才能完成我需要的操作?

The issue is that library doesn't provide support for ripemd160, so how can I add this support in to be able to accomplish what I need?

有一个与此完全相同的问题,但在此处的 Java 中,您可以看到它是如何解决的以及我正在寻找的内容,但这次使用的是 Swift 3:
散列一个字符串Java使用带有密钥的ripemd160模拟php函数hash_hmac

There is a question exactly the same as this but in Java here, you can see how that was solved and exactly what I'm looking for but this time using Swift 3:
Hash a string in Java emulating the php function hash_hmac using ripemd160 with a key

推荐答案

这里是 RIPEMD-160 哈希函数的(自包含的)纯 Swift 5 实现和对应的 HMAC-RIPEMD-160 消息认证码.它已经过测试RIPEMD-160 页面上的所有测试向量(在macOS、32 位 iOS、64 位 iOS).

Here is a (self-contained) pure Swift 5 implementation of the RIPEMD-160 hash function and the corresponding HMAC-RIPEMD-160 message authentication code. It has been tested with all test vectors on the RIPEMD-160 page (tested on macOS, 32-bit iOS, 64-bit iOS).

Swift 3 的代码可以在编辑历史记录中找到.

The code for Swift 3 can be found in the edit history.

这是参考实现的翻译rmd160.h,rmd160.c从 RIPEMD-160 页面从 C 到 Swift.我翻译了辅助宏和 compress()函数(算法的核心")尽可能逐字逐句".这让我能够复制/粘贴大型 C 代码段并仅对 Swift 进行细微调整.

This is a translation of the reference implementation rmd160.h, rmd160.c from the RIPEMD-160 page from C to Swift. I translated the helper macros and the compress() function (the "heart" of the algorithm) as "verbatim" as possible. This allowed me to copy/paste large C code segments and make only minor adjustments for Swift.

update()finalize() 方法提供了一个流接口,类似于CommonCrypto 函数.

The update() and finalize() methods provide a streaming interface, similar to that of the CommonCrypto functions.

RIPEMD160.swift:

import Foundation

public struct RIPEMD160 {

    private var MDbuf: (UInt32, UInt32, UInt32, UInt32, UInt32)
    private var buffer: Data
    private var count: Int64 // Total # of bytes processed.

    public init() {
        MDbuf = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0)
        buffer = Data()
        count = 0
    }

    private mutating func compress(_ X: UnsafePointer<UInt32>) {

        // *** Helper functions (originally macros in rmd160.h) ***

        /* ROL(x, n) cyclically rotates x over n bits to the left */
        /* x must be of an unsigned 32 bits type and 0 <= n < 32. */
        func ROL(_ x: UInt32, _ n: UInt32) -> UInt32 {
            return (x << n) | ( x >> (32 - n))
        }

        /* the five basic functions F(), G() and H() */

        func F(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 {
            return x ^ y ^ z
        }

        func G(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 {
            return (x & y) | (~x & z)
        }

        func H(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 {
            return (x | ~y) ^ z
        }

        func I(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 {
            return (x & z) | (y & ~z)
        }

        func J(_ x: UInt32, _ y: UInt32, _ z: UInt32) -> UInt32 {
            return x ^ (y | ~z)
        }

        /* the ten basic operations FF() through III() */

        func FF(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ F(b, c, d) &+ x
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func GG(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ G(b, c, d) &+ x &+ 0x5a827999
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func HH(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ H(b, c, d) &+ x &+ 0x6ed9eba1
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func II(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ I(b, c, d) &+ x &+ 0x8f1bbcdc
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func JJ(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ J(b, c, d) &+ x &+ 0xa953fd4e
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func FFF(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ F(b, c, d) &+ x
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func GGG(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ G(b, c, d) &+ x &+ 0x7a6d76e9
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func HHH(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ H(b, c, d) &+ x &+ 0x6d703ef3
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func III(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ I(b, c, d) &+ x &+ 0x5c4dd124
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        func JJJ(_ a: inout UInt32, _ b: UInt32, _ c: inout UInt32, _ d: UInt32, _ e: UInt32, _ x: UInt32, _ s: UInt32) {
            a = a &+ J(b, c, d) &+ x &+ 0x50a28be6
            a = ROL(a, s) &+ e
            c = ROL(c, 10)
        }

        // *** The function starts here ***

        var (aa, bb, cc, dd, ee) = MDbuf
        var (aaa, bbb, ccc, ddd, eee) = MDbuf

        /* round 1 */
        FF(&aa, bb, &cc, dd, ee, X[ 0], 11)
        FF(&ee, aa, &bb, cc, dd, X[ 1], 14)
        FF(&dd, ee, &aa, bb, cc, X[ 2], 15)
        FF(&cc, dd, &ee, aa, bb, X[ 3], 12)
        FF(&bb, cc, &dd, ee, aa, X[ 4],  5)
        FF(&aa, bb, &cc, dd, ee, X[ 5],  8)
        FF(&ee, aa, &bb, cc, dd, X[ 6],  7)
        FF(&dd, ee, &aa, bb, cc, X[ 7],  9)
        FF(&cc, dd, &ee, aa, bb, X[ 8], 11)
        FF(&bb, cc, &dd, ee, aa, X[ 9], 13)
        FF(&aa, bb, &cc, dd, ee, X[10], 14)
        FF(&ee, aa, &bb, cc, dd, X[11], 15)
        FF(&dd, ee, &aa, bb, cc, X[12],  6)
        FF(&cc, dd, &ee, aa, bb, X[13],  7)
        FF(&bb, cc, &dd, ee, aa, X[14],  9)
        FF(&aa, bb, &cc, dd, ee, X[15],  8)

        /* round 2 */
        GG(&ee, aa, &bb, cc, dd, X[ 7],  7)
        GG(&dd, ee, &aa, bb, cc, X[ 4],  6)
        GG(&cc, dd, &ee, aa, bb, X[13],  8)
        GG(&bb, cc, &dd, ee, aa, X[ 1], 13)
        GG(&aa, bb, &cc, dd, ee, X[10], 11)
        GG(&ee, aa, &bb, cc, dd, X[ 6],  9)
        GG(&dd, ee, &aa, bb, cc, X[15],  7)
        GG(&cc, dd, &ee, aa, bb, X[ 3], 15)
        GG(&bb, cc, &dd, ee, aa, X[12],  7)
        GG(&aa, bb, &cc, dd, ee, X[ 0], 12)
        GG(&ee, aa, &bb, cc, dd, X[ 9], 15)
        GG(&dd, ee, &aa, bb, cc, X[ 5],  9)
        GG(&cc, dd, &ee, aa, bb, X[ 2], 11)
        GG(&bb, cc, &dd, ee, aa, X[14],  7)
        GG(&aa, bb, &cc, dd, ee, X[11], 13)
        GG(&ee, aa, &bb, cc, dd, X[ 8], 12)

        /* round 3 */
        HH(&dd, ee, &aa, bb, cc, X[ 3], 11)
        HH(&cc, dd, &ee, aa, bb, X[10], 13)
        HH(&bb, cc, &dd, ee, aa, X[14],  6)
        HH(&aa, bb, &cc, dd, ee, X[ 4],  7)
        HH(&ee, aa, &bb, cc, dd, X[ 9], 14)
        HH(&dd, ee, &aa, bb, cc, X[15],  9)
        HH(&cc, dd, &ee, aa, bb, X[ 8], 13)
        HH(&bb, cc, &dd, ee, aa, X[ 1], 15)
        HH(&aa, bb, &cc, dd, ee, X[ 2], 14)
        HH(&ee, aa, &bb, cc, dd, X[ 7],  8)
        HH(&dd, ee, &aa, bb, cc, X[ 0], 13)
        HH(&cc, dd, &ee, aa, bb, X[ 6],  6)
        HH(&bb, cc, &dd, ee, aa, X[13],  5)
        HH(&aa, bb, &cc, dd, ee, X[11], 12)
        HH(&ee, aa, &bb, cc, dd, X[ 5],  7)
        HH(&dd, ee, &aa, bb, cc, X[12],  5)

        /* round 4 */
        II(&cc, dd, &ee, aa, bb, X[ 1], 11)
        II(&bb, cc, &dd, ee, aa, X[ 9], 12)
        II(&aa, bb, &cc, dd, ee, X[11], 14)
        II(&ee, aa, &bb, cc, dd, X[10], 15)
        II(&dd, ee, &aa, bb, cc, X[ 0], 14)
        II(&cc, dd, &ee, aa, bb, X[ 8], 15)
        II(&bb, cc, &dd, ee, aa, X[12],  9)
        II(&aa, bb, &cc, dd, ee, X[ 4],  8)
        II(&ee, aa, &bb, cc, dd, X[13],  9)
        II(&dd, ee, &aa, bb, cc, X[ 3], 14)
        II(&cc, dd, &ee, aa, bb, X[ 7],  5)
        II(&bb, cc, &dd, ee, aa, X[15],  6)
        II(&aa, bb, &cc, dd, ee, X[14],  8)
        II(&ee, aa, &bb, cc, dd, X[ 5],  6)
        II(&dd, ee, &aa, bb, cc, X[ 6],  5)
        II(&cc, dd, &ee, aa, bb, X[ 2], 12)

        /* round 5 */
        JJ(&bb, cc, &dd, ee, aa, X[ 4],  9)
        JJ(&aa, bb, &cc, dd, ee, X[ 0], 15)
        JJ(&ee, aa, &bb, cc, dd, X[ 5],  5)
        JJ(&dd, ee, &aa, bb, cc, X[ 9], 11)
        JJ(&cc, dd, &ee, aa, bb, X[ 7],  6)
        JJ(&bb, cc, &dd, ee, aa, X[12],  8)
        JJ(&aa, bb, &cc, dd, ee, X[ 2], 13)
        JJ(&ee, aa, &bb, cc, dd, X[10], 12)
        JJ(&dd, ee, &aa, bb, cc, X[14],  5)
        JJ(&cc, dd, &ee, aa, bb, X[ 1], 12)
        JJ(&bb, cc, &dd, ee, aa, X[ 3], 13)
        JJ(&aa, bb, &cc, dd, ee, X[ 8], 14)
        JJ(&ee, aa, &bb, cc, dd, X[11], 11)
        JJ(&dd, ee, &aa, bb, cc, X[ 6],  8)
        JJ(&cc, dd, &ee, aa, bb, X[15],  5)
        JJ(&bb, cc, &dd, ee, aa, X[13],  6)

        /* parallel round 1 */
        JJJ(&aaa, bbb, &ccc, ddd, eee, X[ 5],  8)
        JJJ(&eee, aaa, &bbb, ccc, ddd, X[14],  9)
        JJJ(&ddd, eee, &aaa, bbb, ccc, X[ 7],  9)
        JJJ(&ccc, ddd, &eee, aaa, bbb, X[ 0], 11)
        JJJ(&bbb, ccc, &ddd, eee, aaa, X[ 9], 13)
        JJJ(&aaa, bbb, &ccc, ddd, eee, X[ 2], 15)
        JJJ(&eee, aaa, &bbb, ccc, ddd, X[11], 15)
        JJJ(&ddd, eee, &aaa, bbb, ccc, X[ 4],  5)
        JJJ(&ccc, ddd, &eee, aaa, bbb, X[13],  7)
        JJJ(&bbb, ccc, &ddd, eee, aaa, X[ 6],  7)
        JJJ(&aaa, bbb, &ccc, ddd, eee, X[15],  8)
        JJJ(&eee, aaa, &bbb, ccc, ddd, X[ 8], 11)
        JJJ(&ddd, eee, &aaa, bbb, ccc, X[ 1], 14)
        JJJ(&ccc, ddd, &eee, aaa, bbb, X[10], 14)
        JJJ(&bbb, ccc, &ddd, eee, aaa, X[ 3], 12)
        JJJ(&aaa, bbb, &ccc, ddd, eee, X[12],  6)

        /* parallel round 2 */
        III(&eee, aaa, &bbb, ccc, ddd, X[ 6],  9)
        III(&ddd, eee, &aaa, bbb, ccc, X[11], 13)
        III(&ccc, ddd, &eee, aaa, bbb, X[ 3], 15)
        III(&bbb, ccc, &ddd, eee, aaa, X[ 7],  7)
        III(&aaa, bbb, &ccc, ddd, eee, X[ 0], 12)
        III(&eee, aaa, &bbb, ccc, ddd, X[13],  8)
        III(&ddd, eee, &aaa, bbb, ccc, X[ 5],  9)
        III(&ccc, ddd, &eee, aaa, bbb, X[10], 11)
        III(&bbb, ccc, &ddd, eee, aaa, X[14],  7)
        III(&aaa, bbb, &ccc, ddd, eee, X[15],  7)
        III(&eee, aaa, &bbb, ccc, ddd, X[ 8], 12)
        III(&ddd, eee, &aaa, bbb, ccc, X[12],  7)
        III(&ccc, ddd, &eee, aaa, bbb, X[ 4],  6)
        III(&bbb, ccc, &ddd, eee, aaa, X[ 9], 15)
        III(&aaa, bbb, &ccc, ddd, eee, X[ 1], 13)
        III(&eee, aaa, &bbb, ccc, ddd, X[ 2], 11)

        /* parallel round 3 */
        HHH(&ddd, eee, &aaa, bbb, ccc, X[15],  9)
        HHH(&ccc, ddd, &eee, aaa, bbb, X[ 5],  7)
        HHH(&bbb, ccc, &ddd, eee, aaa, X[ 1], 15)
        HHH(&aaa, bbb, &ccc, ddd, eee, X[ 3], 11)
        HHH(&eee, aaa, &bbb, ccc, ddd, X[ 7],  8)
        HHH(&ddd, eee, &aaa, bbb, ccc, X[14],  6)
        HHH(&ccc, ddd, &eee, aaa, bbb, X[ 6],  6)
        HHH(&bbb, ccc, &ddd, eee, aaa, X[ 9], 14)
        HHH(&aaa, bbb, &ccc, ddd, eee, X[11], 12)
        HHH(&eee, aaa, &bbb, ccc, ddd, X[ 8], 13)
        HHH(&ddd, eee, &aaa, bbb, ccc, X[12],  5)
        HHH(&ccc, ddd, &eee, aaa, bbb, X[ 2], 14)
        HHH(&bbb, ccc, &ddd, eee, aaa, X[10], 13)
        HHH(&aaa, bbb, &ccc, ddd, eee, X[ 0], 13)
        HHH(&eee, aaa, &bbb, ccc, ddd, X[ 4],  7)
        HHH(&ddd, eee, &aaa, bbb, ccc, X[13],  5)

        /* parallel round 4 */
        GGG(&ccc, ddd, &eee, aaa, bbb, X[ 8], 15)
        GGG(&bbb, ccc, &ddd, eee, aaa, X[ 6],  5)
        GGG(&aaa, bbb, &ccc, ddd, eee, X[ 4],  8)
        GGG(&eee, aaa, &bbb, ccc, ddd, X[ 1], 11)
        GGG(&ddd, eee, &aaa, bbb, ccc, X[ 3], 14)
        GGG(&ccc, ddd, &eee, aaa, bbb, X[11], 14)
        GGG(&bbb, ccc, &ddd, eee, aaa, X[15],  6)
        GGG(&aaa, bbb, &ccc, ddd, eee, X[ 0], 14)
        GGG(&eee, aaa, &bbb, ccc, ddd, X[ 5],  6)
        GGG(&ddd, eee, &aaa, bbb, ccc, X[12],  9)
        GGG(&ccc, ddd, &eee, aaa, bbb, X[ 2], 12)
        GGG(&bbb, ccc, &ddd, eee, aaa, X[13],  9)
        GGG(&aaa, bbb, &ccc, ddd, eee, X[ 9], 12)
        GGG(&eee, aaa, &bbb, ccc, ddd, X[ 7],  5)
        GGG(&ddd, eee, &aaa, bbb, ccc, X[10], 15)
        GGG(&ccc, ddd, &eee, aaa, bbb, X[14],  8)

        /* parallel round 5 */
        FFF(&bbb, ccc, &ddd, eee, aaa, X[12] ,  8)
        FFF(&aaa, bbb, &ccc, ddd, eee, X[15] ,  5)
        FFF(&eee, aaa, &bbb, ccc, ddd, X[10] , 12)
        FFF(&ddd, eee, &aaa, bbb, ccc, X[ 4] ,  9)
        FFF(&ccc, ddd, &eee, aaa, bbb, X[ 1] , 12)
        FFF(&bbb, ccc, &ddd, eee, aaa, X[ 5] ,  5)
        FFF(&aaa, bbb, &ccc, ddd, eee, X[ 8] , 14)
        FFF(&eee, aaa, &bbb, ccc, ddd, X[ 7] ,  6)
        FFF(&ddd, eee, &aaa, bbb, ccc, X[ 6] ,  8)
        FFF(&ccc, ddd, &eee, aaa, bbb, X[ 2] , 13)
        FFF(&bbb, ccc, &ddd, eee, aaa, X[13] ,  6)
        FFF(&aaa, bbb, &ccc, ddd, eee, X[14] ,  5)
        FFF(&eee, aaa, &bbb, ccc, ddd, X[ 0] , 15)
        FFF(&ddd, eee, &aaa, bbb, ccc, X[ 3] , 13)
        FFF(&ccc, ddd, &eee, aaa, bbb, X[ 9] , 11)
        FFF(&bbb, ccc, &ddd, eee, aaa, X[11] , 11)

        /* combine results */
        MDbuf = (MDbuf.1 &+ cc &+ ddd,
                 MDbuf.2 &+ dd &+ eee,
                 MDbuf.3 &+ ee &+ aaa,
                 MDbuf.4 &+ aa &+ bbb,
                 MDbuf.0 &+ bb &+ ccc)
    }

    public mutating func update(data: Data) {
        var X = [UInt32](repeating: 0, count: 16)
        var pos = data.startIndex
        var length = data.count

        // Process remaining bytes from last call:
        if buffer.count > 0 && buffer.count + length >= 64 {
            let amount = 64 - buffer.count
            buffer.append(data[..<amount])
            X.withUnsafeMutableBytes {
                _ = buffer.copyBytes(to: $0)
            }
            compress(X)
            pos += amount
            length -= amount
        }

        // Process 64 byte chunks:
        while length >= 64 {
            X.withUnsafeMutableBytes {
                _ = data[pos..<pos+64].copyBytes(to: $0)
            }
            compress(X)
            pos += 64
            length -= 64
        }

        // Save remaining unprocessed bytes:
        buffer = data[pos...]
        count += Int64(data.count)
    }

    public mutating func finalize() -> Data {
        var X = [UInt32](repeating: 0, count: 16)
        /* append the bit m_n == 1 */
        buffer.append(0x80)
        X.withUnsafeMutableBytes {
            _ = buffer.copyBytes(to: $0)
        }

        if (count & 63) > 55 {
            /* length goes to next block */
            compress(X)
            X = [UInt32](repeating: 0, count: 16)
        }

        /* append length in bits */
        let lswlen = UInt32(truncatingIfNeeded: count)
        let mswlen = UInt32(UInt64(count) >> 32)
        X[14] = lswlen << 3
        X[15] = (lswlen >> 29) | (mswlen << 3)
        compress(X)

        buffer = Data()
        let result = [MDbuf.0, MDbuf.1, MDbuf.2, MDbuf.3, MDbuf.4]
        return result.withUnsafeBytes { Data($0) }
    }
}

这里是一次性"函数来计算消息的哈希值(以 Data 形式给出)或作为 String):

And here are "one-shot" functions to compute the hash of a message (given as Data or as String):

RIPEMD160-Ext.swift:

import Foundation

public extension RIPEMD160 {

    static func hash(message: Data) -> Data {
        var md = RIPEMD160()
        md.update(data: message)
        return md.finalize()
    }

    static func hash(message: String) -> Data {
        return RIPEMD160.hash(message: message.data(using: .utf8)!)
    }
}

最后是对应的消息认证码.算法采取从伪代码在维基百科:基于哈希的消息认证代码:

Finally, the corresponding message authentication code. The algorithm is taken from the pseudo-code at Wikipedia: Hash-based message authentication code:

RIPEMD160-HMAC.swift:

import Foundation

public extension RIPEMD160 {

    static func hmac(key: Data, message: Data) -> Data {

        var key = key
        key.count = 64 // Truncate to 64 bytes or fill-up with zeros.

        let outerKeyPad = Data(key.map { $0 ^ 0x5c })
        let innerKeyPad = Data(key.map { $0 ^ 0x36 })

        var innerMd = RIPEMD160()
        innerMd.update(data: innerKeyPad)
        innerMd.update(data: message)

        var outerMd = RIPEMD160()
        outerMd.update(data: outerKeyPad)
        outerMd.update(data: innerMd.finalize())

        return outerMd.finalize()
    }

    static func hmac(key: Data, message: String) -> Data {
        return RIPEMD160.hmac(key: key, message: message.data(using: .utf8)!)
    }

    static func hmac(key: String, message: String) -> Data {
        return RIPEMD160.hmac(key: key.data(using: .utf8)!, message: message)
    }
}

示例

要将消息摘要打印为十六进制编码的字符串,请使用以下方法如何在swift中将数据转换为十六进制字符串可以使用:

extension Data {
    func hexEncodedString() -> String {
        return map { String(format: "%02hhx", $0) }.joined()
    }
}

示例 1:

let msg = "Hello World"
let hash = RIPEMD160.hash(message: msg).hexEncodedString()
print(hash) // a830d7beb04eb7549ce990fb7dc962e499a27230

示例 2(您的示例):

Example 2 (your example):

let hmac = RIPEMD160.hmac(key: "test", message: "string").hexEncodedString()
print(hmac) // 37241f2513c60ae4d9b3b8d0d30517445f451fa5

这篇关于Swift 使用带有ripemd160 的hash_hmac 散列一个字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆