使用 hash_hmac 和ripemd160 快速散列字符串

2024-03-17

我正在尝试使用 Swift 3 (和/或 Objective C)对字符串进行哈希处理ripemd160模拟以下 php 的输出:

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

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

// outputs: 37241f2513c60ae4d9b3b8d0d30517445f451fa5


So far:

我尝试过调查hash_hmac我能找到的功能,例如:
在swift中实现HMAC和SHA1加密 https://stackoverflow.com/questions/26970807/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>

Issue

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


有一个与此完全相同的问题,但在 Java 中,您可以看到这个问题是如何解决的以及我正在寻找的内容,但这次使用 Swift 3:
使用ripemd160和密钥对Java中的字符串进行哈希模拟php函数hash_hmac https://stackoverflow.com/questions/39568562/hash-a-string-in-java-emulating-the-php-function-hash-hmac-using-ripemd160-with


这是一个(独立的)纯Swift 5RIPEMD-160 哈希函数的实现和 对应的HMAC-RIPEMD-160消息认证码。它已经过测试 所有测试向量RIPEMD-160 页 http://homes.esat.kuleuven.be/~bosselae/ripemd160.html(测试于 macOS、32 位 iOS、64 位 iOS)。

代码为Swift 3可以在编辑历史中找到。

这是参考实现的翻译rmd160.h http://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd160.h, rmd160.c http://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd160.c从 RIPEMD-160 页面从 C 到 Swift。我翻译了辅助宏和compress()函数(算法的“核心”)尽可能“逐字记录”。这让我能够 复制/粘贴大型 C 代码段,并仅对 Swift 进行细微调整。

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

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 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)!)
    }
}

最后是对应的消息验证码。算法采取 来自伪代码维基百科:基于哈希的消息验证代码 https://en.wikipedia.org/wiki/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)
    }
}

Examples

要将消息摘要打印为十六进制编码的字符串,请使用以下方法如何在 swift 中将数据转换为十六进制字符串 https://stackoverflow.com/questions/39075043/how-to-convert-data-to-hex-string-in-swift/40089462#40089462可以使用:

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(您的示例):

let hmac = RIPEMD160.hmac(key: "test", message: "string").hexEncodedString()
print(hmac) // 37241f2513c60ae4d9b3b8d0d30517445f451fa5
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 hash_hmac 和ripemd160 快速散列字符串 的相关文章

  • 应用内购买自定义价格

    我已经搜索了一段时间 但它可能太明显了 人们不会发布它 我想知道是否可以为产品设定动态价格 我有送货申请 价格可能会因距离而异 此外 它也可以是非整数价格 例如 2 43 美元 是否可以 另外 我无法在 iTunes Connect 上设定
  • 有什么方法可以限制核心数据中的重复条目吗?

    我一直在尝试在核心数据中添加对象 所以 我希望它不应该允许核心数据存储中出现重复的条目 怎么做 这是我与保存数据相关的代码 IBAction save id sender if name text isEqualToString addre
  • 如何实现pickerView类的didSelectRow方法?

    我以前从未使用过选择器视图 我认为它类似于表视图类的 func tableView tableView UITableView didDeselectRowAtIndexPath indexPath NSIndexPath 方法 但是我无法
  • 在 UIAlertController 的文本字段中选择文本

    我需要在 UIAlertController 出现后立即选择文本字段的文本 但是 我在标准 UITextField 中选择文本的方式在这里不起作用 这就是我尝试过的 但我似乎无法让它发挥作用 let ac UIAlertController
  • 将 iCloud 数据迁移到本地存储并阻止 iCloud 继续响应

    我即将在我的应用程序中完成 iCloud 和 Core Data 的实现 这是一款仅限 iOS 7 的应用程序 我在应用程序中为用户提供了一个选项 以 打开 或 关闭 的形式显示 使用 iCloud UISwitch 该应用程序启动时会询问
  • TweetNaCl.js 最小公钥签名示例

    我试图了解如何基于位于的演示来实现一个最小的基本公钥签名示例here https tweetnacl js org sign 使用纯javascript 我的研究还没有产生一个简单的 javascript 示例 我可以用它来理解其内部工作原
  • 如何在 Objective-C + Cocoa 中创建自定义无边框 NSWindow?

    首先我要说的是 这是我的第一个真正的 Cocoa 应用程序 这是一个简单的应用程序 几乎在无边框窗口中显示我的网站 我目前创建无边框窗口的方式使用以下内容 void awakeFromNib window setStyleMask NSBo
  • 在 macOS 中获取用户首选的温度设置

    我正在尝试读取温度单位 摄氏度 华氏度 的用户设置系统首选项 我试图使用 NSLocale 获取此数据 但我找不到任何温度设置的证据 甚至可以读取这些数据吗 Thanks 官方 API 记录在首选项 实用程序 https developer
  • iOS 中特定字符串的 SHA1

    根据我的要求 输入字符串必须转换为字节值 string 的每个字符都是 16 位值 必须转换为低 8 位 然后在字节数组上计算 Sha1 生成的 SHA 1 将转换为 40 个字符的字符串 我知道如何将字符串转换为 SHA1 但其余部分对我
  • 为什么数据没有填充在我的自定义 ui 表视图单元格中

    我正在从服务器获取数据 我想将其放入我的自定义 UITableViewCell 中 这是故事板中的单元格 如您所见 有两件事 首选项标签 三个按钮 当我从服务器接收数据时 我这样做 override func tableView table
  • 使用 Swift 的核心数据瞬态值

    有谁知道 或者有一个例子 如何使用 Swift 处理核心数据瞬态值 我知道在属性之前使用 NSManaged 但无法弄清楚如何编写逻辑以使用 Swift 构建瞬态值 复选标记短暂的数据模型中特定属性的字段 例如sectionTitle 为该
  • 如何检测和处理UIWebView中的HTTP错误代码?

    我想在收到 HTTP 错误 404 等时通知用户 我怎样才能检测到这一点 我已经尝试过实施 void webView UIWebView webView didFailLoadWithError NSError error 但当我收到 40
  • 使用 Core Audio 忽略 __cxa_throw 是否安全?

    一个相似的question https stackoverflow com questions 12861748 how do i know when safe to ignore cxa throw on an all exception
  • 为什么这段代码不能产生正确的输出? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 给定一个字符串和一个数字 该函数将从
  • 为 Swift 中的Optional提供默认值?

    如果您只想在 nil 的情况下提供默认值 那么在 Swift 中处理可选值的习惯用法似乎过于冗长 if let value optionalValue do something with value else do the same thi
  • 协议扩展,不符合协议

    我正在创建一个名为MyFramework含有LoginProtocol swift它有一些默认行为 import UIKit public protocol LoginProtocol func appBannerImage gt UIIm
  • 检查 NSIndexPath 的行和部分的开关

    我想设置一个 switch 语句来检查值 ifNSIndexPath NSIndexPath是一个类 它由 除其他外 部分和行组成 indexPath row indexPath section 这就是我如何制定 if 语句来同时检查行和部
  • 应用内购买导致偶尔崩溃

    我在互联网上搜索了这方面的帮助 但没有结果 我的应用程序已在应用程序商店中上线 少数用户报告应用程序在进行应用内购买后冻结并崩溃 我的游戏中唯一的 IAP 它基本上解锁了完整版本 即使他们重新启动设备并尝试继续 设备也会再次崩溃 我无法重现
  • 使用 Objective C 将 html 字符串插入 sqlite 数据库

    我正在使用下面的代码片段将 html 字符串插入 sqlite 数据库 我的代码工作正常 但是当我检索相同的 html 字符串并在 Web 视图中显示时 它不会呈现 一些数据正在被修改 任何人都可以帮助如何插入长 html 字符串存入数据库
  • 如何在 UIButton 中创建边框?

    我在名为 addButton 的应用程序中使用自定义按钮 我想用白色边框它 如何在自定义按钮周围获得白色边框 您可以通过访问按钮的图层属性来设置 CALayer 上的边框属性 首先 添加石英 import

随机推荐