SPB Git

spb/os-vault Public

Self-custody, multi-chain crypto wallet for macOS. One recovery phrase, six chain families, zero API keys — nothing leaves your Mac.

Swift 96% Shell 3.4% Makefile 0.6%
2.9 KB · 98 lines swift
Raw Blame History
1import Foundation23/// Bignum compatibility alias for BInt4public typealias Bignum = BInt56public extension Bignum {7    /// Representation as Data8    var data: Data {9        let n = limbs.count10        var data = Data(count: n * 8)11        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in12            var p = ptr13            for i in (0 ..< n).reversed() {14                for j in (0 ..< 8).reversed() {15                    p.pointee = UInt8((limbs[i] >> UInt64(j * 8)) & 0xFF)16                    p += 117                }18            }19        }20        return data21    }2223    /// Decimal string representation24    var dec: String { description }2526    /// Hexadecimal string representation27    var hex: String { data.hexString }2829    ///30    /// Initialise a BInt from a hexadecimal string31    ///32    /// - Parameter hex: the hexadecimal string to convert to a big integer33    init(hex: String) {34        self.init(number: hex.lowercased(), withBase: 16)35    }3637    /// Initialise from an unsigned, 64 bit integer38    ///39    /// - Parameter n: the 64 bit unsigned integer to convert to a BInt40    init(_ n: UInt64) {41        self.init(limbs: [n])42    }4344    /// Initialise from big-endian data45    ///46    /// - Parameter data: the data to convert to a Bignum47    init(data: Data) {48        let n = data.count49        guard n > 0 else {50            self.init(0)51            return52        }53        let m = (n + 7) / 854        var limbs = Limbs(repeating: 0, count: m)55        data.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in56            var p = ptr57            let r = n % 858            let k = r == 0 ? 8 : r59            for j in (0 ..< k).reversed() {60                limbs[m - 1] += UInt64(p.pointee) << UInt64(j * 8)61                p += 162            }63            guard m > 1 else { return }64            for i in (0 ..< (m - 1)).reversed() {65                for j in (0 ..< 8).reversed() {66                    limbs[i] += UInt64(p.pointee) << UInt64(j * 8)67                    p += 168                }69            }70        }71        self.init(limbs: limbs)72    }73}7475/// Extension for Data to interoperate with Bignum76public extension Data {77    /// Hexadecimal string representation of the underlying data78    var hexString: String {79        withUnsafeBytes { (buf: UnsafePointer<UInt8>) -> String in80            let charA = UInt8(UnicodeScalar("a").value)81            let char0 = UInt8(UnicodeScalar("0").value)8283            func itoh(_ value: UInt8) -> UInt8 {84                (value > 9) ? (charA + value - 10) : (char0 + value)85            }8687            let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: count * 2)8889            for i in 0 ..< count {90                ptr[i * 2] = itoh((buf[i] >> 4) & 0xF)91                ptr[i * 2 + 1] = itoh(buf[i] & 0xF)92            }9394            return String(bytesNoCopy: ptr, length: count * 2, encoding: .utf8, freeWhenDone: true)!95        }96    }97}98