mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 22:45:19 +00:00
Unify SHA256 hash and hex usages (#687)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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,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()
|
||||
|
||||
Reference in New Issue
Block a user