From 06ea5a8a4c8cb86bae7864952215fae22f8fe87d Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 5 Jul 2020 00:47:08 -0700 Subject: [PATCH] Bootstrap swift package creation --- .gitignore | 17 +++--- .gitmodules | 3 + LICENSE | 2 +- Package.swift | 55 ++++++++++++++++++ README.md | 65 +++++++++++++++++++++- Sources/secp256k1/include/secp256k1.h | 4 ++ Sources/secp256k1/secp256k1 | 1 + Tests/LinuxMain.swift | 7 +++ Tests/secp256k1Tests/XCTestManifests.swift | 9 +++ Tests/secp256k1Tests/secp256k1Tests.swift | 47 ++++++++++++++++ bitrise.yml | 28 ++++++++++ 11 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 .gitmodules create mode 100644 Package.swift create mode 100644 Sources/secp256k1/include/secp256k1.h create mode 160000 Sources/secp256k1/secp256k1 create mode 100644 Tests/LinuxMain.swift create mode 100644 Tests/secp256k1Tests/XCTestManifests.swift create mode 100644 Tests/secp256k1Tests/secp256k1Tests.swift create mode 100644 bitrise.yml diff --git a/.gitignore b/.gitignore index 330d167..e24354d 100644 --- a/.gitignore +++ b/.gitignore @@ -34,17 +34,20 @@ DerivedData/ timeline.xctimeline playground.xcworkspace +## macOS +.DS_Store + # Swift Package Manager # # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. -# Packages/ -# Package.pins -# Package.resolved -# *.xcodeproj -# +Packages/ +Package.pins +Package.resolved +*.xcodeproj + # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata # hence it is not needed unless you have added a package configuration file to your project -# .swiftpm +.swiftpm .build/ @@ -57,7 +60,7 @@ playground.xcworkspace # Pods/ # # Add this line if you want to avoid checking in source code from the Xcode workspace -# *.xcworkspace +*.xcworkspace # Carthage # diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..dee59d2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Sources/secp256k1/secp256k1"] + path = Sources/secp256k1/secp256k1 + url = https://github.com/bitcoin-core/secp256k1 diff --git a/LICENSE b/LICENSE index a07ceb1..38d91bf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 GigaBitcoin +Copyright (c) 2020 GigaBitcoin LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..c9f507a --- /dev/null +++ b/Package.swift @@ -0,0 +1,55 @@ +// swift-tools-version:5.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "secp256k1", + products: [ + // The `libsecp256k1` bindings to programatically work with Swift. + // + // WARNING: These APIs should not be considered stable and may change at any time. + .library( + name: "secp256k1", + targets: ["secp256k1"] + ) + ], + targets: [ + .target( + name: "secp256k1", + path: "Sources/secp256k1", + exclude: [ + "secp256k1/src/asm", + "secp256k1/src/bench_ecdh.c", + "secp256k1/src/bench_ecmult.c", + "secp256k1/src/bench_internal.c", + "secp256k1/src/bench_recover.c", + "secp256k1/src/bench_sign.c", + "secp256k1/src/bench_verify.c", + "secp256k1/src/gen_context.c", + "secp256k1/src/tests_exhaustive.c", + "secp256k1/src/tests.c", + "secp256k1/src/valgrind_ctime_test.c" + ], + cSettings: [ + .headerSearchPath("secp256k1"), + // Basic config values that are universal and require no dependencies. + // + // https://github.com/bitcoin-core/secp256k1/blob/master/src/basic-config.h#L29-L34 + .define("USE_NUM_NONE"), + .define("USE_FIELD_INV_BUILTIN"), + .define("USE_SCALAR_INV_BUILTIN"), + .define("USE_FIELD_10X26"), + .define("USE_SCALAR_8X32"), + .define("ECMULT_WINDOW_SIZE", to: "15", nil), + .define("ECMULT_GEN_PREC_BITS", to: "4", nil) + ] + ), + .testTarget( + name: "secp256k1Tests", + dependencies: ["secp256k1"] + ) + ], + swiftLanguageVersions: [.v5], + cLanguageStandard: .c89 +) diff --git a/README.md b/README.md index 77b4c91..6f1584d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,63 @@ -# secp256k1.swift -Swift bindings library for ECDSA signatures and secret/public key operations using the libsecp256k1 C library. +# 🔐 secp256k1.swift +Swift bindings library for ECDSA signatures and secret/public key operations using the [libsecp256k1](https://github.com/bitcoin-core/secp256k1) C library. + +# Objective +This library aims is to be a lightweight dependency for clients and wrapper libraries to include ECDSA functionality. + +This package targets the default git branch of secp256k1 and aims to stay up-to-date without using a mirrored repository. + +# Getting Started + +In your `Package.swift`: + +```swift +dependencies: [ + .package(name: "secp256k1", url: "https://github.com/GigaBitcoin/secp256k1.swift.git", from: "0.0.1"), +] +``` + +Currently, this Swift package only provides a single product library built using the `libsecp256k1` [basic config](https://github.com/bitcoin-core/secp256k1/blob/master/src/basic-config.h). + +# Usage + +```swift +import secp256k1 + +// Initialize context +let context = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY))! + +// Setup private and public key variables +var pubkeyLen = 65 +var cPubkey = secp256k1_pubkey() +var pubkey = [UInt8](repeating: 0, count: pubkeyLen) +let privkey: [UInt8] = [0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,0,0,1,0,0,1,1,0,0,1,0,0,32,0] + +// Verify the context and keys are setup correctly +guard secp256k1_context_randomize(context, privkey) == 1, + secp256k1_ec_pubkey_create(context, &cPubkey, privkey) == 1, + secp256k1_ec_pubkey_serialize(context, &pubkey, &pubkeyLen, &cPubkey, UInt32(SECP256K1_EC_UNCOMPRESSED)) == 1 else { + // Destory context after creation + secp256k1_context_destroy(context) + return +} + +print(pubkey) // [4,96,104, 212, 128, 165, 213, 207, 134, 132, 22, 247, 38, 114, 82, 108, 77, 43, 6, 56, ... ] + +// Destory context after creation +secp256k1_context_destroy(context) +``` + +# Contributing + +To start developing, clone the package from github, and from the root directory, run the following commands: + +```shell +git submodule update --init +swift build +``` + +Tests can be run by calling `swift test` + +# Danger +These APIs should not be considered stable and may change at any time. libsecp256k1 is still experimental and has not been formally released. + diff --git a/Sources/secp256k1/include/secp256k1.h b/Sources/secp256k1/include/secp256k1.h new file mode 100644 index 0000000..b83517a --- /dev/null +++ b/Sources/secp256k1/include/secp256k1.h @@ -0,0 +1,4 @@ +#include "../secp256k1/include/secp256k1_ecdh.h" +#include "../secp256k1/include/secp256k1_preallocated.h" +#include "../secp256k1/include/secp256k1_recovery.h" +#include "../secp256k1/include/secp256k1.h" \ No newline at end of file diff --git a/Sources/secp256k1/secp256k1 b/Sources/secp256k1/secp256k1 new file mode 160000 index 0000000..3f4a5a1 --- /dev/null +++ b/Sources/secp256k1/secp256k1 @@ -0,0 +1 @@ +Subproject commit 3f4a5a10e43bfc8dae5b978cb39aa2dfbaf4d713 diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..e1e384f --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +import XCTest + +import secp256k1Tests + +var tests = [XCTestCaseEntry]() +tests += secp256k1Tests.allTests() +XCTMain(tests) diff --git a/Tests/secp256k1Tests/XCTestManifests.swift b/Tests/secp256k1Tests/XCTestManifests.swift new file mode 100644 index 0000000..0687b7e --- /dev/null +++ b/Tests/secp256k1Tests/XCTestManifests.swift @@ -0,0 +1,9 @@ +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(secp256k1Tests.allTests), + ] +} +#endif diff --git a/Tests/secp256k1Tests/secp256k1Tests.swift b/Tests/secp256k1Tests/secp256k1Tests.swift new file mode 100644 index 0000000..d47b98a --- /dev/null +++ b/Tests/secp256k1Tests/secp256k1Tests.swift @@ -0,0 +1,47 @@ +import XCTest +@testable import secp256k1 + +final class secp256k1Tests: XCTestCase { + /// Basic Keypair test + func testKeypairCreation() { + // Initialize context + let context = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY))! + + // Destory context after execution + defer { + secp256k1_context_destroy(context) + } + + // Setup private and public key variables + var pubkeyLen = 65 + var cPubkey = secp256k1_pubkey() + var pubkey = [UInt8](repeating: 0, count: pubkeyLen) + let privkey: [UInt8] = [0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,0,0,1,0,0,1,1,0,0,1,0,0,32,0] + + // Verify the context and keys are setup correctly + XCTAssertEqual(secp256k1_context_randomize(context, privkey), 1) + XCTAssertEqual(secp256k1_ec_pubkey_create(context, &cPubkey, privkey), 1) + XCTAssertEqual(secp256k1_ec_pubkey_serialize(context, &pubkey, &pubkeyLen, &cPubkey, UInt32(SECP256K1_EC_UNCOMPRESSED)), 1) + + // Define the expected public key + let expectedPublicKey: [UInt8] = [ + 4,96,104, 212, 128, 165, 213, + 207, 134, 132, 22, 247, 38, + 114, 82, 108, 77, 43, 6, 56, + 80, 113, 12, 11, 119, 7, 240, + 188, 73, 170, 44, 202, 33, 225, + 30, 248, 53, 138, 34, 22, 100, + 96, 31, 76, 64, 125, 71, 127, + 62, 155, 108, 243, 17, 222, 97, + 234, 75, 247, 187, 83, 151, 206, + 27, 38, 228 + ] + + // Verify the generated public key matches the expected public key + XCTAssertEqual(expectedPublicKey, pubkey) + } + + static var allTests = [ + ("testKeypairCreation", testKeypairCreation), + ] +} diff --git a/bitrise.yml b/bitrise.yml new file mode 100644 index 0000000..0e611ed --- /dev/null +++ b/bitrise.yml @@ -0,0 +1,28 @@ +--- +format_version: '8' +default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git +project_type: other +trigger_map: +- push_branch: "*" + workflow: Entry-Workflow +- pull_request_source_branch: "*" + workflow: Entry-Workflow +workflows: + Distribute: + steps: + - swift-package-manager-test-for-mac@0: {} + - deploy-to-bitrise-io@1: {} + Entry-Workflow: + steps: + - activate-ssh-key@4: + run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' + - git-clone@4: {} + - script@1: + title: Trigger Bitrise Workflow + inputs: + - content: bitrise --ci run --secret-filtering --workflow Code-Review --config + bitrise.yml + Code-Review: + steps: + - swift-package-manager-test-for-mac@0: {} + - deploy-to-bitrise-io@1: {}