Unify SHA256 hash and hex usages (#687)

This commit is contained in:
Islam
2025-09-30 12:47:16 +02:00
committed by GitHub
parent f5af00be88
commit 78fb3f1bf6
14 changed files with 50 additions and 82 deletions
+2 -2
View File
@@ -397,7 +397,7 @@ final class NoiseSymmetricState {
if nameData.count <= 32 {
self.hash = nameData + Data(repeating: 0, count: 32 - nameData.count)
} else {
self.hash = Data(SHA256.hash(data: nameData))
self.hash = nameData.sha256Hash()
}
self.chainingKey = self.hash
}
@@ -410,7 +410,7 @@ final class NoiseSymmetricState {
}
func mixHash(_ data: Data) {
hash = Data(SHA256.hash(data: hash + data))
hash = (hash + data).sha256Hash()
}
func mixKeyAndHash(_ inputKeyMaterial: Data) {
@@ -8,7 +8,6 @@
import BitLogger
import Foundation
import CryptoKit
// MARK: - Security Constants
+1 -4
View File
@@ -226,10 +226,7 @@ struct NostrIdentityBridge {
}
}
// As a final fallback, hash the seed+msg and try again
var combined = Data()
combined.append(seed)
combined.append(msg)
let fallback = Data(CryptoKit.SHA256.hash(data: combined))
let fallback = (seed + msg).sha256Hash()
return try NostrIdentity(privateKeyData: fallback)
}
}
+1 -4
View File
@@ -521,10 +521,7 @@ struct NostrEvent: Codable {
] as [Any]
let data = try JSONSerialization.data(withJSONObject: serialized, options: [.withoutEscapingSlashes])
let hash = CryptoKit.SHA256.hash(data: data)
let hashData = Data(hash)
let hashHex = hash.compactMap { String(format: "%02x", $0) }.joined()
return (hashHex, hashData)
return (data.sha256Fingerprint(), data.sha256Hash())
}
func jsonString() throws -> String {
+1 -1
View File
@@ -197,7 +197,7 @@ extension Data {
offset += 16
// Convert 16 bytes to UUID string format
let uuid = uuidData.map { String(format: "%02x", $0) }.joined()
let uuid = uuidData.hexEncodedString()
// Insert hyphens at proper positions: 8-4-4-4-12
var result = ""
-14
View File
@@ -1,14 +0,0 @@
import Foundation
import CryptoKit
// MARK: - Peer ID Utilities
struct PeerIDUtils {
/// Derive the stable 16-hex peer ID from a Noise static public key
static func derivePeerID(fromPublicKey publicKey: Data) -> String {
let digest = SHA256.hash(data: publicKey)
let hex = digest.map { String(format: "%02x", $0) }.joined()
return String(hex.prefix(16))
}
}
+9
View File
@@ -0,0 +1,9 @@
import Foundation
struct PeerIDUtils {
/// Derive the stable 16-hex peer ID from a Noise static public key
static func derivePeerID(fromPublicKey publicKey: Data) -> String {
String(publicKey.sha256Fingerprint().prefix(16))
}
}
+8 -19
View File
@@ -264,8 +264,7 @@ final class BLEService: NSObject {
// MARK: - Helpers: IDs, selection, and write backpressure
private func makeMessageID(for packet: BitchatPacket) -> String {
let senderID = packet.senderID.hexEncodedString()
let digest = SHA256.hash(data: packet.payload)
let digestPrefix = digest.prefix(4).map { String(format: "%02x", $0) }.joined()
let digestPrefix = packet.payload.sha256Hash().prefix(4).hexEncodedString()
return "\(senderID)-\(packet.timestamp)-\(packet.type)-\(digestPrefix)"
}
@@ -777,12 +776,7 @@ final class BLEService: NSObject {
func getPeerFingerprint(_ peerID: String) -> String? {
return collectionsQueue.sync {
if let publicKey = peers[peerID]?.noisePublicKey {
// Use the same fingerprinting method as NoiseEncryptionService/UnifiedPeerService (SHA-256 of raw key)
let hash = SHA256.hash(data: publicKey)
return hash.map { String(format: "%02x", $0) }.joined()
}
return nil
return peers[peerID]?.noisePublicKey?.sha256Fingerprint()
}
}
@@ -1705,17 +1699,12 @@ final class BLEService: NSObject {
}
// Persist cryptographic identity and signing key for robust offline verification
do {
// Derive fingerprint from Noise public key
let hash = SHA256.hash(data: announcement.noisePublicKey)
let fingerprint = hash.map { String(format: "%02x", $0) }.joined()
identityManager.upsertCryptographicIdentity(
fingerprint: fingerprint,
noisePublicKey: announcement.noisePublicKey,
signingPublicKey: announcement.signingPublicKey,
claimedNickname: announcement.nickname
)
}
identityManager.upsertCryptographicIdentity(
fingerprint: announcement.noisePublicKey.sha256Fingerprint(),
noisePublicKey: announcement.noisePublicKey,
signingPublicKey: announcement.signingPublicKey,
claimedNickname: announcement.nickname
)
// Record this announce for lightweight rebroadcast buffer (exclude self)
if peerID != myPeerID {
@@ -272,8 +272,7 @@ final class NoiseEncryptionService {
/// Get our identity fingerprint
func getIdentityFingerprint() -> String {
let hash = SHA256.hash(data: staticIdentityPublicKey.rawRepresentation)
return hash.map { String(format: "%02x", $0) }.joined()
staticIdentityPublicKey.rawRepresentation.sha256Fingerprint()
}
/// Get peer's public key data
@@ -554,7 +553,7 @@ final class NoiseEncryptionService {
private func handleSessionEstablished(peerID: String, remoteStaticKey: Curve25519.KeyAgreement.PublicKey) {
// Calculate fingerprint
let fingerprint = calculateFingerprint(for: remoteStaticKey)
let fingerprint = remoteStaticKey.rawRepresentation.sha256Fingerprint()
// Store fingerprint mapping
serviceQueue.sync(flags: .barrier) {
@@ -572,11 +571,6 @@ final class NoiseEncryptionService {
}
}
}
private func calculateFingerprint(for publicKey: Curve25519.KeyAgreement.PublicKey) -> String {
let hash = SHA256.hash(data: publicKey.rawRepresentation)
return hash.map { String(format: "%02x", $0) }.joined()
}
// MARK: - Session Maintenance
-11
View File
@@ -10,7 +10,6 @@ import BitLogger
import Foundation
import Combine
import SwiftUI
import CryptoKit
/// Single source of truth for peer state, combining mesh connectivity and favorites
@MainActor
@@ -389,13 +388,3 @@ final class UnifiedPeerService: ObservableObject, TransportPeerEventsDelegate {
})
}
}
// MARK: - Helper Extensions
extension Data {
func sha256Fingerprint() -> String {
// Implementation matches existing fingerprint generation in NoiseEncryptionService
let hash = SHA256.hash(data: self)
return hash.map { String(format: "%02x", $0) }.joined()
}
}
+1 -2
View File
@@ -1,5 +1,4 @@
import Foundation
import CryptoKit
/// QR verification scaffolding: schema, signing, and basic challenge/response helpers.
final class VerificationService {
@@ -95,7 +94,7 @@ final class VerificationService {
nickname: payload.nickname,
ts: payload.ts,
nonceB64: payload.nonceB64,
sigHex: sig.map { String(format: "%02x", $0) }.joined())
sigHex: sig.hexEncodedString())
let out = signed.toURLString()
Cache.last = (nickname, npub, Date(), out)
return out
+22
View File
@@ -0,0 +1,22 @@
//
// Data+SHA256.swift
// bitchat
//
// Created by Islam on 26/09/2025.
//
import struct Foundation.Data
import struct CryptoKit.SHA256
extension Data {
/// Returns the hex representation of SHA256 hash
func sha256Fingerprint() -> String {
// Implementation matches existing fingerprint generation in NoiseEncryptionService
sha256Hash().hexEncodedString()
}
/// Returns the SHA256 hash wrapped in Data
func sha256Hash() -> Data {
Data(SHA256.hash(data: self))
}
}
+3 -10
View File
@@ -80,7 +80,6 @@
import BitLogger
import Foundation
import SwiftUI
import CryptoKit
import Combine
import CommonCrypto
import CoreBluetooth
@@ -1299,10 +1298,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// Called when we receive a peer's public key
@MainActor
func registerPeerPublicKey(peerID: String, publicKeyData: Data) {
// Create a fingerprint from the public key (full SHA256, not truncated)
let fingerprintStr = SHA256.hash(data: publicKeyData)
.compactMap { String(format: "%02x", $0) }
.joined()
let fingerprintStr = publicKeyData.sha256Fingerprint()
// Only register if not already registered
if peerIDToPublicKeyFingerprint[peerID] != fingerprintStr {
@@ -5184,11 +5180,8 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
}
// Validate recipient
if let rid = packet.recipientID {
let ridHex = rid.map { String(format: "%02x", $0) }.joined()
if ridHex != meshService.myPeerID {
return
}
if let rid = packet.recipientID, rid.hexEncodedString() != meshService.myPeerID {
return
}
// Parse plaintext typed payload
-6
View File
@@ -6,16 +6,10 @@
//
import XCTest
import CryptoKit
@testable import bitchat
final class NostrProtocolTests: XCTestCase {
override func setUp() {
super.setUp()
// SecureLogger is always enabled
}
func testNIP17MessageRoundTrip() throws {
// Create sender and recipient identities
let sender = try NostrIdentity.generate()