如何解决除空字符串
我正在尝试创建自己的哈希框架/库,但是偶然发现了一个问题。当我计算一个空字符串的SHA256哈希值时,该哈希值被成功计算,但是当我为其他内容计算时,它失败了。有人可以帮我找出原因吗?
由Wikipedia提供,当在线执行并使用python时,此哈希匹配。
let h = SHA256(message: Data("".utf8))
let d = h.digest()
// e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
print(d)
但是“ Hello world”不是
let h = SHA256(message: Data("Hello world".utf8))
let d = h.digest()
// ce9f4c08f0688d09b8061ed6692c1d5af2516c8682fad2d9a5d72f96ba787a80
print(d)
// Expected:
// 64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c
我希望有人能帮助我。下面的SHA256实现:
/*
First 32 bits of the fractional parts of the
square roots of the first 8 primes 2..19.
*/
fileprivate let kSHA256H0: UInt32 = 0x6a09e667
fileprivate let kSHA256H1: UInt32 = 0xbb67ae85
fileprivate let kSHA256H2: UInt32 = 0x3c6ef372
fileprivate let kSHA256H3: UInt32 = 0xa54ff53a
fileprivate let kSHA256H4: UInt32 = 0x510e527f
fileprivate let kSHA256H5: UInt32 = 0x9b05688c
fileprivate let kSHA256H6: UInt32 = 0x1f83d9ab
fileprivate let kSHA256H7: UInt32 = 0x5be0cd19
/*
First 32 bits of the fractional parts of the
cube roots of the first 64 primes 2..311.
*/
fileprivate let kSHA256K: [UInt32] = [
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
]
/// Shift the value of x n amount to the right.
/// - Parameters:
/// - x: The value to shift.
/// - n: The amount to shift by.
/// - Returns: The shifted value.
fileprivate func shiftRight(_ x: UInt32,_ n: UInt32) -> UInt32 { x >> n }
/// Rotate the value of x n amount of times.
/// - Parameters:
/// - x: The value to rotate.
/// - y: The amount to rotate by.
/// - Returns: The rotated value.
fileprivate func rotateRight(_ x: UInt32,_ y: UInt32) -> UInt32 { (x >> (y & 31)) | (x << (32 - (y & 31))) }
/// Split data into chunks of specified size.
/// - Note: This function will not pad or append data
/// to make sure all the chunks are equal in size.
/// - Parameters:
/// - data: The data to split.
/// - size: The size of a chunk.
/// - Returns: An array containing chunks of specified size (when able).
fileprivate func chunk(_ data: Data,toSize size: Int) -> [Data] {
stride(from: 0,to: data.count,by: size).map {
data.subdata(in: $0 ..< Swift.min($0 + size,data.count))
}
}
public class SHA256 {
/// The pre-processed data.
fileprivate let message: Data
fileprivate var hash = [
kSHA256H0,kSHA256H1,kSHA256H2,kSHA256H3,kSHA256H4,kSHA256H5,kSHA256H6,kSHA256H7
]
public init(message: Data) {
self.message = Self.preProcess(message: message)
}
fileprivate static func preProcess(message: Data) -> Data {
let L = message.count * 8 // Original message length in bits.
var K = 0 // Required padding bits.
while (L + 1 + K + 64) % 512 != 0 {
K += 1
}
var padding = Data(repeating: 0,count: K / 8)
padding.insert(0x80,at: 0) // Insert 1000 0000 into the padding.
var length = UInt64(L).bigEndian
return message + padding + Data(bytes: &length,count: 8)
}
public func digest() -> Data {
let chunks = chunk(message,toSize: 64)
for chunk in chunks {
var w = [UInt32](repeating: 0,count: 64) // 64-entry message schedule array of 32-bit words.
// Copy the chunk into first 16 words w[0..15] of the schedule array.
for i in 0 ..< 16 {
let sub = chunk.subdata(in: i ..< i + 4)
w[i] = sub.withUnsafeBytes { $0.load(as: UInt32.self) }.bigEndian
}
// Extend the first 16 words into the remaining 48 words w[16..63] of the schedule array.
for i in 16 ..< 64 {
let s0 = rotateRight(w[i - 15],7) ^ rotateRight(w[i - 15],18) ^ shiftRight(w[i - 15],3)
let s1 = rotateRight(w[i - 2],17) ^ rotateRight(w[i - 2],19) ^ shiftRight(w[i - 2],10)
w[i] = s1 &+ w[i - 7] &+ s0 &+ w[i - 16]
}
// Create some working variables.
var a = hash[0]
var b = hash[1]
var c = hash[2]
var d = hash[3]
var e = hash[4]
var f = hash[5]
var g = hash[6]
var h = hash[7]
// Compress function main loop.
for i in 0 ..< 64 {
let S1 = rotateRight(e,6) ^ rotateRight(e,11) ^ rotateRight(e,25)
let ch = (e & f) ^ (~e & g)
let T1 = h &+ S1 &+ ch &+ kSHA256K[i] &+ w[i]
let S0 = rotateRight(a,2) ^ rotateRight(a,13) ^ rotateRight(a,22)
let maj = (a & b) ^ (a & c) ^ (b & c)
let T2 = S0 &+ maj
h = g
g = f
f = e
e = d &+ T1
d = c
c = b
b = a
a = T1 &+ T2
}
hash[0] &+= a
hash[1] &+= b
hash[2] &+= c
hash[3] &+= d
hash[4] &+= e
hash[5] &+= f
hash[6] &+= g
hash[7] &+= h
}
return hash.map {
var num = $0.bigEndian
return Data(bytes: &num,count: 4)
}.reduce(Data(),+)
}
}
解决方法
结果是,我创建了错误的子数据以构造我的UInt32
来创建消息调度数组。 (.digest()
函数的前几行)
旧的是
let sub = chunk.subdata(in: i ..< i + 4)
新的是
let sub = chunk.subdata(in: i * 4 ..< (i * 4) + 4)
这解决了问题
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。