Skip to content

Commit

Permalink
add function and tests to convert public key to public key hash
Browse files Browse the repository at this point in the history
  • Loading branch information
simonmcl committed May 8, 2024
1 parent f8e81c7 commit 9c07785
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Sources/KukaiCryptoSwift/KeyPair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ public enum EllipticalCurve: String, Codable {
else if prefix == "tz2" { return .secp256k1 }
else { return nil }
}

public static func fromBase58Key(_ key: String) -> EllipticalCurve? {
let prefix = key.lowercased().prefix(4)

if prefix == "edpk" { return .ed25519 }
else if prefix == "sppk" { return .secp256k1 }
else { return nil }
}
}

/// A struct representing a both a `PrivateKey` and `PublicKey` with helper methods to create various kinds
Expand Down
19 changes: 19 additions & 0 deletions Sources/KukaiCryptoSwift/PublicKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,25 @@ public struct PublicKey: Codable {
return secp256k1_ecdsa_verify(context, &cSignature, message, &publicKey) == 1
}
}

/**
Take a base58Encoded public key (with a prefix) and convert it to a tzX public key hash
*/
public static func publicKeyHash(fromBase58EncodedKey key: String) -> String? {
guard let algo = EllipticalCurve.fromBase58Key(key),
let decoded = Base58Check.decode(string: key, prefix: algo == .ed25519 ? Prefix.Keys.Ed25519.public : Prefix.Keys.Secp256k1.public),
let hash = Sodium.shared.genericHash.hash(message: decoded, outputLength: 20) else {
return nil
}

switch algo {
case .ed25519:
return Base58Check.encode(message: hash, prefix: Prefix.Address.tz1)

case .secp256k1:
return Base58Check.encode(message: hash, prefix: Prefix.Address.tz2)
}
}
}

extension PublicKey: CustomStringConvertible {
Expand Down
14 changes: 14 additions & 0 deletions Tests/KukaiCryptoSwiftTests/KeyPairTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,18 @@ final class KeyPairTests: XCTestCase {
let pubKeySafety = KeyPair.secp256k1PublicKey(fromPrivateKeyBytes: signatureBytes)
XCTAssert(pubKeySafety == nil, (pubKeySafety?.bytes.count ?? 0).description)
}

func testKeyToHash() throws {
let hash1 = PublicKey.publicKeyHash(fromBase58EncodedKey: "edpkuLshcvrn2x7c2QtCCMv8XFNEM2gHkPDGb3paKt2hBvnBRfepR4")
XCTAssert(hash1 == "tz1Xx4vxaUCkgxfaUhr1EV1kvTE2Rt3BkEdm", hash1 ?? "-")

let hash2 = PublicKey.publicKeyHash(fromBase58EncodedKey: "edpkuaUnRZQzwP1QYHFFXzbhN919wg17KHm7vHH86pxxgSSkqT7U4a")
XCTAssert(hash2 == "tz1ZYoRJ2iouRi5r6CT83Ptp9Bof7RMRkxXe", hash2 ?? "-")

let hash3 = PublicKey.publicKeyHash(fromBase58EncodedKey: "edpkufQ3nNdMJBkgfzCgCLmk1tbfLsqK7W8AR37KiCe7tDVvmsroHh")
XCTAssert(hash3 == "tz1WCBJKr1rRivyCnN9hREpRAMqrLdmqDcym", hash3 ?? "-")

let hash4 = PublicKey.publicKeyHash(fromBase58EncodedKey: "sppk7Zzqz2AjP4yXqr5ys99gZkaPLFKfGKnUxn3u1T1xfNSArZ5CKX6")
XCTAssert(hash4 == "tz2HpbGQcmU3UyusJ78Sbqeg9fYteamSMDGo", hash4 ?? "-")
}
}

0 comments on commit 9c07785

Please sign in to comment.