First commit.
This commit is contained in:
commit
481e1cffa7
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# OS X
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
*.xccheckout
|
||||
profile
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
# Bundler
|
||||
.bundle
|
||||
|
||||
Carthage/Build
|
||||
Pods/
|
||||
14
.travis.yml
Normal file
14
.travis.yml
Normal file
@ -0,0 +1,14 @@
|
||||
# references:
|
||||
# * https://www.objc.io/issues/6-build-tools/travis-ci/
|
||||
# * https://github.com/supermarin/xcpretty#usage
|
||||
|
||||
osx_image: xcode7.3
|
||||
language: objective-c
|
||||
# cache: cocoapods
|
||||
# podfile: Example/Podfile
|
||||
# before_install:
|
||||
# - gem install cocoapods # Since Travis is not always on latest version
|
||||
# - pod install --project-directory=Example
|
||||
script:
|
||||
- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/AirgappedSigning.xcworkspace -scheme AirgappedSigning-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
|
||||
- pod lib lint
|
||||
28
AirgappedSigning.podspec
Normal file
28
AirgappedSigning.podspec
Normal file
@ -0,0 +1,28 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'AirgappedSigning'
|
||||
s.version = '0.1.0'
|
||||
s.summary = 'A protocol for transmission of messages between hot and cold cryptographic wallets.'
|
||||
|
||||
# s.description = <<-DESC
|
||||
# TODO: Add long description of the pod here.
|
||||
# DESC
|
||||
|
||||
s.homepage = 'https://github.com/wolfmcnally/AirgappedSigning'
|
||||
s.license = { :type => 'Apache', :file => 'LICENSE' }
|
||||
s.author = { 'Wolf McNally' => 'wolf@wolfmcnally.com' }
|
||||
s.source = { :git => 'https://github.com/blockchainCommons/AirgappedSigning.git', :tag => s.version.to_s }
|
||||
|
||||
s.source_files = 'Sources/AirgappedSigning/**/*'
|
||||
|
||||
s.swift_version = '5.0'
|
||||
|
||||
s.ios.deployment_target = '11.0'
|
||||
# s.macos.deployment_target = '10.13'
|
||||
# s.tvos.deployment_target = '11.0'
|
||||
|
||||
s.module_name = 'AirgappedSigning'
|
||||
|
||||
s.dependency 'Bitcoin'
|
||||
s.dependency 'WolfCore'
|
||||
s.dependency 'NonEmpty'
|
||||
end
|
||||
148
Docs/AirgappedSigningExamples.md
Normal file
148
Docs/AirgappedSigningExamples.md
Normal file
@ -0,0 +1,148 @@
|
||||
# Airgapped Signing Protocol Examples
|
||||
|
||||
### Examples
|
||||
|
||||
Note that while the examples in this section should validate against the JSON schema, these examples are not test vectors and should not be expected to validate. Please see the JSON schema below for further explanatory comments.
|
||||
|
||||
#### MultiPart
|
||||
|
||||
Used when a document is too large to fit into a packet (like a QR code) and must be broken into multiple parts. The concatenated `data` fields must decode to another document in this specification.
|
||||
|
||||
```json
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"multiPart": {
|
||||
"uid": "449C40FE-E207-4AC9-B552-51B007B68D50",
|
||||
"part": 0,
|
||||
"count": 1,
|
||||
"data": "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4K"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### RecoveryWords
|
||||
|
||||
Used to back up the seed from which all other keys are derived. The passphrase (if any) is never transmitted in this structure-- it is always entered directly by the user.
|
||||
|
||||
```json
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"recoveryWords": {
|
||||
"name": "Rainy Day",
|
||||
"format": "BIP39",
|
||||
"words": ["panda", "diary", "marriage", "suffer", "basic", "glare", "surge", "auto", "scissors", "describe", "sell", "unique"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### KnownReceiver
|
||||
|
||||
Used to send the address of a known receiver to the cold wallet to be used when confirming the contents of transactions.
|
||||
|
||||
```json
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"knownReceiver": {
|
||||
"name": "Example",
|
||||
"asset": "BTC",
|
||||
"address": "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Account
|
||||
|
||||
Used to send a public key, asset, and associated account path to the hot wallet to be used in watching the block chain and/or creating new transactions.
|
||||
|
||||
```json
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"account": {
|
||||
"name": "Example Account",
|
||||
"asset": "BTC",
|
||||
"hdPublicKey": "xpub6CUGRUonZSQ4TWtTMmzXdrXDtypWKiKrhko4egpiMZbpiaQL2jkwSB1icqYh2cfDfVxdx4df189oLKnC5fSwqPfgyP3hooxujYzAu3fDVmz",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Transaction Signing Request
|
||||
|
||||
"Transaction" as used here is rougly equivalent to a Partially Signed Bitcoin Transaction (PSBT). It is designed so multiple parties can provide inputs, outputs, and signatures to be combined later.
|
||||
|
||||
```json
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"transaction": {
|
||||
"uid": "819AACCF-984A-43EF-AC1D-D4CD37C9A7DC",
|
||||
"asset": "BTC",
|
||||
"inputs": [
|
||||
{
|
||||
"uid": "A6B0DF6D-E670-4233-8EAC-626C0A9AAC9A",
|
||||
"txHash": "ba34fa2ed2c42e7ba66887a96d22e14dec1244a3c47b271cd69a679afbaab868",
|
||||
"inputIndex": 1,
|
||||
"sender": "18f8tN4PLdCXF2JHy5PjRerqXg994yGme3",
|
||||
"derivation": {
|
||||
"accountIndex": 0,
|
||||
"addressIndex": 12
|
||||
},
|
||||
"amount": 59943910
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"uid": "79296757-6C80-49BF-996F-87FCB46A566C",
|
||||
"receiver": "1N5YvoDTEbkKsE1SiPEKbih6BM1HAD3dV9",
|
||||
"amount": 9240
|
||||
},
|
||||
{
|
||||
"uid": "69F19CB5-A9B1-4C80-B5CA-A304E37C04C7",
|
||||
"receiver": "19MUKz42a951wmXtJBa5fdvRvGvAGh6NDG",
|
||||
"derivation": {
|
||||
"accountIndex": 0,
|
||||
"addressIndex": 4
|
||||
},
|
||||
"amount": 59855564
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Transaction Signing Response
|
||||
|
||||
This example is a reply from the cold wallet that signs the input provided in the previous example.
|
||||
|
||||
```json
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"transaction": {
|
||||
"uid": "819AACCF-984A-43EF-AC1D-D4CD37C9A7DC",
|
||||
"inputSignatures": [
|
||||
{
|
||||
"uid": "A6B0DF6D-E670-4233-8EAC-626C0A9AAC9A",
|
||||
"ecPublicKey": "AzfAJTIa8S38RRcVnZvZgWTdL/n715cbKdCqJx1yxATK",
|
||||
"ecSignature": "MEQCIBBhpg0KAmDqJu/0v/L8a9kCWGMNh3QVLYpq/tfzEQdmAiAMLrZKT5H2maQXPvEm6iYTNIcpKk6B+8Lg4z+xaLVCbAE="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
326
Docs/AirgappedSigningSchema.json
Normal file
326
Docs/AirgappedSigningSchema.json
Normal file
@ -0,0 +1,326 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "http://blockchaincommons.org/schemas/AirgappedSigning.json",
|
||||
"$comment": "This scheme follows the convention of naming keys with `Capitalized` words when they represent types, and `lowercased` words when they represent instances. In general, `camelCase` is used for identifiers.",
|
||||
"definitions": {
|
||||
"Name": {
|
||||
"$comment": "A human-assigned name for an object. In required field lists herein, `name` is intentionally left optional.",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"UID": {
|
||||
"$comment": "A unique identifier used to associate messages or parts of documents.",
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"Asset": {
|
||||
"$comment": "Identifies a particular kind of asset, for example Bitcoin. Could also represent the type of any other document capable of being signed.\n`BTC`: Bitcoin, `BTCT`: Bitcoin Testnet.",
|
||||
"type": "string",
|
||||
"enum": ["BTC", "BTCT"]
|
||||
},
|
||||
"Fragments": {
|
||||
"$comment": "A whole number count of the smallest unit of an asset; in the case of Bitcoin, the Satoshi.",
|
||||
"type": "number",
|
||||
"multipleOf": 1
|
||||
},
|
||||
"MultiPart": {
|
||||
"$comment": "Used when a document is too large to fit into a packet (like a QR code) and must be broken into multiple parts. The `data` field contains a base64-encoded chunck of another document that conforms to this spec.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": {
|
||||
"$comment": "`uid` must be the same for every part of the same multipart document.",
|
||||
"$ref": "#/definitions/UID"
|
||||
},
|
||||
"part": {
|
||||
"type": "number",
|
||||
"multipleOf": 1,
|
||||
"minimum": 0,
|
||||
"$comment": "Zero-based. Must be < `count`."
|
||||
},
|
||||
"count": {
|
||||
"type": "number",
|
||||
"multipleOf": 1,
|
||||
"minimum": 1
|
||||
},
|
||||
"data": {
|
||||
"type": "string",
|
||||
"contentEncoding": "base64"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"uid",
|
||||
"part",
|
||||
"count",
|
||||
"data"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"RecoveryWords": {
|
||||
"$comment": "A list of recovery words used for BIP39 or similar.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "$ref": "#/definitions/Name" },
|
||||
"format": { "enum": ["BIP39"] },
|
||||
"words": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 100,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 30
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"format",
|
||||
"words"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"PaymentAddress": {
|
||||
"$comment": "A payment address.",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"KnownReceiver": {
|
||||
"$comment": "A payment address associated with a name and asset type.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "$ref": "#/definitions/Name" },
|
||||
"asset": { "$ref": "#/definitions/Asset" },
|
||||
"address": { "$ref": "#/definitions/PaymentAddress" }
|
||||
},
|
||||
"required": [
|
||||
"asset",
|
||||
"address"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AccountIndex": {
|
||||
"$comment": "The `account` part of a BIP44 derivation path.",
|
||||
"type": "number",
|
||||
"multipleOf": 1,
|
||||
"minimum": 0
|
||||
},
|
||||
"AddressIndex": {
|
||||
"$comment": "The `address_index` part of a BIP44 derivation path.",
|
||||
"type": "number",
|
||||
"multipleOf": 1,
|
||||
"minimum": 0
|
||||
},
|
||||
"HDPublicKey": {
|
||||
"$comment": "An HD public key that can be watched for activity on the network, and from which payment addresses can be derived.",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"ECPublicKey": {
|
||||
"$comment": "A public key that can be used as part of a transaction signing.",
|
||||
"type": "string",
|
||||
"contentEncoding": "base64"
|
||||
},
|
||||
"ECSignature": {
|
||||
"$comment": "An EC signature.",
|
||||
"type": "string",
|
||||
"contentEncoding": "base64"
|
||||
},
|
||||
"Account": {
|
||||
"$comment": "A particular account derived from a particular public key.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "$ref": "#/definitions/Name" },
|
||||
"asset": { "$ref": "#/definitions/Asset" },
|
||||
"hdPublicKey": { "$ref": "#/definitions/HDPublicKey" },
|
||||
"index": { "$ref": "#/definitions/AccountIndex" }
|
||||
},
|
||||
"required": [
|
||||
"asset",
|
||||
"hdPublicKey",
|
||||
"index"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Derivation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountIndex": { "$ref": "#/definitions/AccountIndex" },
|
||||
"addressIndex": { "$ref": "#/definitions/AddressIndex" },
|
||||
},
|
||||
"required": [
|
||||
"accountIndex",
|
||||
"addressIndex"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Input": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": {
|
||||
"$comment": "Associates this input with its signature(s).",
|
||||
"$ref": "#/definitions/UID"
|
||||
},
|
||||
"txHash": { "type": "string" },
|
||||
"inputIndex": { "type": "number" },
|
||||
"sender": {
|
||||
"$comment": "Which private key to use for signing can be determined by searching for the private key from which `sender` can be derived by applying `accountIndex` and `addressIndex` in the derivation path.",
|
||||
"$ref": "#/definitions/PaymentAddress"
|
||||
},
|
||||
"derivation": { "$ref": "#/definitions/Derivation" },
|
||||
"amount": { "$ref": "#/definitions/Fragments" }
|
||||
},
|
||||
"required": [
|
||||
"uid",
|
||||
"txHash",
|
||||
"inputIndex",
|
||||
"sender",
|
||||
"derivation",
|
||||
"amount"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Output": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": { "$ref": "#/definitions/UID" },
|
||||
"receiver": { "$ref": "#/definitions/PaymentAddress" },
|
||||
"amount": { "$ref": "#/definitions/Fragments" },
|
||||
"derivation": { "$ref": "#/definitions/Derivation" }
|
||||
},
|
||||
"required": [
|
||||
"uid",
|
||||
"receiver",
|
||||
"amount"
|
||||
],
|
||||
"$comment": "`derivation` intentionally left optional because only change outputs need a derivation path so they can be confirmed as spendable.",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"InputSignature": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": {
|
||||
"$comment": "Associates this signature with an input in the transaction.",
|
||||
"$ref": "#/definitions/UID"
|
||||
},
|
||||
"ecPublicKey": {
|
||||
"$comment": "The public key which corresponds to this signature.",
|
||||
"$ref": "#/definitions/ECPublicKey"
|
||||
},
|
||||
"ecSignature": {
|
||||
"$comment": "The signature as would be pushed to the stack from a scriptSig or witness.",
|
||||
"$ref": "#/definitions/ECSignature"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"uid",
|
||||
"ecPublicKey",
|
||||
"ecSignature"
|
||||
]
|
||||
},
|
||||
"Transaction": {
|
||||
"$comment": "Roughly equivalent to a Partially Signed Bitcoin Transaction (PSBT). Designed so multiple parties can provide inputs, outputs, and signatures to be combined later.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": {
|
||||
"$comment": "`uid` must be the same for all messages of the same signing transaction.",
|
||||
"$ref": "#/definitions/UID"
|
||||
},
|
||||
"asset": { "$ref": "#/definitions/Asset" },
|
||||
"inputs": {
|
||||
"$comment": "If present, may not be empty.",
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/Input" }
|
||||
},
|
||||
"outputs": {
|
||||
"$comment": "If present, may not be empty.",
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/Output" }
|
||||
},
|
||||
"inputSignatures": {
|
||||
"$comment": "If present, may not be empty.",
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/InputSignature" }
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"uid"
|
||||
],
|
||||
"$comment": "`asset`, `inputs`, `outputs`, and `inputSignatures` intentionally left optional for representing partial transactions.",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Header": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": { "const": "AirgappedSigning" },
|
||||
"version": { "const": 1 }
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"version"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": { "$ref": "#/definitions/Header" },
|
||||
"multiPart": { "$ref": "#/definitions/MultiPart" }
|
||||
},
|
||||
"required": [
|
||||
"header",
|
||||
"multiPart"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": { "$ref": "#/definitions/Header" },
|
||||
"recoveryWords": { "$ref": "#/definitions/RecoveryWords" }
|
||||
},
|
||||
"required": [
|
||||
"header",
|
||||
"recoveryWords"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": { "$ref": "#/definitions/Header" },
|
||||
"knownReceiver": { "$ref": "#/definitions/KnownReceiver" }
|
||||
},
|
||||
"required": [
|
||||
"header",
|
||||
"knownReceiver"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": { "$ref": "#/definitions/Header" },
|
||||
"account": { "$ref": "#/definitions/Account" }
|
||||
},
|
||||
"required": [
|
||||
"header",
|
||||
"account"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": { "$ref": "#/definitions/Header" },
|
||||
"transaction": { "$ref": "#/definitions/Transaction" }
|
||||
},
|
||||
"required": [
|
||||
"header",
|
||||
"transaction"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
610
Example/AirgappedSigning.xcodeproj/project.pbxproj
Normal file
610
Example/AirgappedSigning.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,610 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
|
||||
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
|
||||
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
|
||||
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
|
||||
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
|
||||
607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; };
|
||||
BC2B1DE04520DF63ECB1180C /* Pods_AirgappedSigning_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0482D64EDEE9715D175CF016 /* Pods_AirgappedSigning_Tests.framework */; };
|
||||
EF6DB9BDC7D6962179D78605 /* Pods_AirgappedSigning_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94FEB700BCF9984F9E44F826 /* Pods_AirgappedSigning_Example.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 607FACCF1AFB9204008FA782;
|
||||
remoteInfo = AirgappedSigning;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0355E88BCB373C4803A6A18C /* AirgappedSigning.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = AirgappedSigning.podspec; path = ../AirgappedSigning.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
|
||||
0482D64EDEE9715D175CF016 /* Pods_AirgappedSigning_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirgappedSigning_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05D0FE05BA7A72641201C4E1 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
|
||||
4EB2C27D3619D1CA0346AA96 /* Pods-AirgappedSigning_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirgappedSigning_Tests.debug.xcconfig"; path = "Target Support Files/Pods-AirgappedSigning_Tests/Pods-AirgappedSigning_Tests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
51400B6C08379C0E6EC2285F /* Pods-AirgappedSigning_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirgappedSigning_Tests.release.xcconfig"; path = "Target Support Files/Pods-AirgappedSigning_Tests/Pods-AirgappedSigning_Tests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5E267DBE350210DDA6D5F071 /* Pods-AirgappedSigning_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirgappedSigning_Example.debug.xcconfig"; path = "Target Support Files/Pods-AirgappedSigning_Example/Pods-AirgappedSigning_Example.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
607FACD01AFB9204008FA782 /* AirgappedSigning_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AirgappedSigning_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
607FACE51AFB9204008FA782 /* AirgappedSigning_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirgappedSigning_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
|
||||
653EE703F7545ACADEA15A65 /* Pods-AirgappedSigning_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirgappedSigning_Example.release.xcconfig"; path = "Target Support Files/Pods-AirgappedSigning_Example/Pods-AirgappedSigning_Example.release.xcconfig"; sourceTree = "<group>"; };
|
||||
844B88A490A39412A1A97776 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
|
||||
94FEB700BCF9984F9E44F826 /* Pods_AirgappedSigning_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirgappedSigning_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
607FACCD1AFB9204008FA782 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
EF6DB9BDC7D6962179D78605 /* Pods_AirgappedSigning_Example.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
607FACE21AFB9204008FA782 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BC2B1DE04520DF63ECB1180C /* Pods_AirgappedSigning_Tests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
2E2E27C47B446D8DF8E09FC9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5E267DBE350210DDA6D5F071 /* Pods-AirgappedSigning_Example.debug.xcconfig */,
|
||||
653EE703F7545ACADEA15A65 /* Pods-AirgappedSigning_Example.release.xcconfig */,
|
||||
4EB2C27D3619D1CA0346AA96 /* Pods-AirgappedSigning_Tests.debug.xcconfig */,
|
||||
51400B6C08379C0E6EC2285F /* Pods-AirgappedSigning_Tests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5A95E4B96D10D8515149C1BF /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
94FEB700BCF9984F9E44F826 /* Pods_AirgappedSigning_Example.framework */,
|
||||
0482D64EDEE9715D175CF016 /* Pods_AirgappedSigning_Tests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACC71AFB9204008FA782 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACF51AFB993E008FA782 /* Podspec Metadata */,
|
||||
607FACD21AFB9204008FA782 /* Example for AirgappedSigning */,
|
||||
607FACE81AFB9204008FA782 /* Tests */,
|
||||
607FACD11AFB9204008FA782 /* Products */,
|
||||
2E2E27C47B446D8DF8E09FC9 /* Pods */,
|
||||
5A95E4B96D10D8515149C1BF /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACD11AFB9204008FA782 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACD01AFB9204008FA782 /* AirgappedSigning_Example.app */,
|
||||
607FACE51AFB9204008FA782 /* AirgappedSigning_Tests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACD21AFB9204008FA782 /* Example for AirgappedSigning */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACD51AFB9204008FA782 /* AppDelegate.swift */,
|
||||
607FACD71AFB9204008FA782 /* ViewController.swift */,
|
||||
607FACD91AFB9204008FA782 /* Main.storyboard */,
|
||||
607FACDC1AFB9204008FA782 /* Images.xcassets */,
|
||||
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
|
||||
607FACD31AFB9204008FA782 /* Supporting Files */,
|
||||
);
|
||||
name = "Example for AirgappedSigning";
|
||||
path = AirgappedSigning;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACD31AFB9204008FA782 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACD41AFB9204008FA782 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACE81AFB9204008FA782 /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACEB1AFB9204008FA782 /* Tests.swift */,
|
||||
607FACE91AFB9204008FA782 /* Supporting Files */,
|
||||
);
|
||||
path = Tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACE91AFB9204008FA782 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACEA1AFB9204008FA782 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0355E88BCB373C4803A6A18C /* AirgappedSigning.podspec */,
|
||||
05D0FE05BA7A72641201C4E1 /* README.md */,
|
||||
844B88A490A39412A1A97776 /* LICENSE */,
|
||||
);
|
||||
name = "Podspec Metadata";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
607FACCF1AFB9204008FA782 /* AirgappedSigning_Example */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "AirgappedSigning_Example" */;
|
||||
buildPhases = (
|
||||
D1057688AA0D43C557F0FCBA /* [CP] Check Pods Manifest.lock */,
|
||||
607FACCC1AFB9204008FA782 /* Sources */,
|
||||
607FACCD1AFB9204008FA782 /* Frameworks */,
|
||||
607FACCE1AFB9204008FA782 /* Resources */,
|
||||
288882641AE88ECD39CD0290 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = AirgappedSigning_Example;
|
||||
productName = AirgappedSigning;
|
||||
productReference = 607FACD01AFB9204008FA782 /* AirgappedSigning_Example.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
607FACE41AFB9204008FA782 /* AirgappedSigning_Tests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "AirgappedSigning_Tests" */;
|
||||
buildPhases = (
|
||||
31D8847F2CE4CC7175566907 /* [CP] Check Pods Manifest.lock */,
|
||||
607FACE11AFB9204008FA782 /* Sources */,
|
||||
607FACE21AFB9204008FA782 /* Frameworks */,
|
||||
607FACE31AFB9204008FA782 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
607FACE71AFB9204008FA782 /* PBXTargetDependency */,
|
||||
);
|
||||
name = AirgappedSigning_Tests;
|
||||
productName = Tests;
|
||||
productReference = 607FACE51AFB9204008FA782 /* AirgappedSigning_Tests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
607FACC81AFB9204008FA782 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = WolfMcNally.com;
|
||||
TargetAttributes = {
|
||||
607FACCF1AFB9204008FA782 = {
|
||||
CreatedOnToolsVersion = 6.3.1;
|
||||
LastSwiftMigration = 0900;
|
||||
};
|
||||
607FACE41AFB9204008FA782 = {
|
||||
CreatedOnToolsVersion = 6.3.1;
|
||||
LastSwiftMigration = 0900;
|
||||
TestTargetID = 607FACCF1AFB9204008FA782;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "AirgappedSigning" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 607FACC71AFB9204008FA782;
|
||||
productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
607FACCF1AFB9204008FA782 /* AirgappedSigning_Example */,
|
||||
607FACE41AFB9204008FA782 /* AirgappedSigning_Tests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
607FACCE1AFB9204008FA782 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */,
|
||||
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */,
|
||||
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
607FACE31AFB9204008FA782 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
288882641AE88ECD39CD0290 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-AirgappedSigning_Example/Pods-AirgappedSigning_Example-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/AirgappedSigning/AirgappedSigning.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Bitcoin/Bitcoin.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/CBitcoin/CBitcoin.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/ExtensibleEnumeratedName/ExtensibleEnumeratedName.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/NonEmpty/NonEmpty.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfConcurrency/WolfConcurrency.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfCore/WolfCore.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfFoundation/WolfFoundation.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfNesting/WolfNesting.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfNumerics/WolfNumerics.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfOSBridge/WolfOSBridge.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfPipe/WolfPipe.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfStrings/WolfStrings.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/WolfWith/WolfWith.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AirgappedSigning.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Bitcoin.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CBitcoin.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ExtensibleEnumeratedName.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NonEmpty.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfConcurrency.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfCore.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfFoundation.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfNesting.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfNumerics.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfOSBridge.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfPipe.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfStrings.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WolfWith.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AirgappedSigning_Example/Pods-AirgappedSigning_Example-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
31D8847F2CE4CC7175566907 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-AirgappedSigning_Tests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D1057688AA0D43C557F0FCBA /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-AirgappedSigning_Example-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
607FACCC1AFB9204008FA782 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
|
||||
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
607FACE11AFB9204008FA782 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
607FACEC1AFB9204008FA782 /* Tests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
607FACE71AFB9204008FA782 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 607FACCF1AFB9204008FA782 /* AirgappedSigning_Example */;
|
||||
targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
607FACD91AFB9204008FA782 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
607FACDA1AFB9204008FA782 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
607FACDF1AFB9204008FA782 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
607FACED1AFB9204008FA782 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
607FACEE1AFB9204008FA782 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
607FACF01AFB9204008FA782 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5E267DBE350210DDA6D5F071 /* Pods-AirgappedSigning_Example.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = AirgappedSigning/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MODULE_NAME = ExampleApp;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
607FACF11AFB9204008FA782 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 653EE703F7545ACADEA15A65 /* Pods-AirgappedSigning_Example.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = AirgappedSigning/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MODULE_NAME = ExampleApp;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
607FACF31AFB9204008FA782 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 4EB2C27D3619D1CA0346AA96 /* Pods-AirgappedSigning_Tests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Tests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AirgappedSigning_Example.app/AirgappedSigning_Example";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
607FACF41AFB9204008FA782 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 51400B6C08379C0E6EC2285F /* Pods-AirgappedSigning_Tests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Tests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AirgappedSigning_Example.app/AirgappedSigning_Example";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "AirgappedSigning" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
607FACED1AFB9204008FA782 /* Debug */,
|
||||
607FACEE1AFB9204008FA782 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "AirgappedSigning_Example" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
607FACF01AFB9204008FA782 /* Debug */,
|
||||
607FACF11AFB9204008FA782 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "AirgappedSigning_Tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
607FACF31AFB9204008FA782 /* Debug */,
|
||||
607FACF41AFB9204008FA782 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 607FACC81AFB9204008FA782 /* Project object */;
|
||||
}
|
||||
7
Example/AirgappedSigning.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
Example/AirgappedSigning.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:AirgappedSigning.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
|
||||
BuildableName = "AirgappedSigning_Example.app"
|
||||
BlueprintName = "AirgappedSigning_Example"
|
||||
ReferencedContainer = "container:AirgappedSigning.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "607FACE41AFB9204008FA782"
|
||||
BuildableName = "AirgappedSigning_Tests.xctest"
|
||||
BlueprintName = "AirgappedSigning_Tests"
|
||||
ReferencedContainer = "container:AirgappedSigning.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "607FACE41AFB9204008FA782"
|
||||
BuildableName = "AirgappedSigning_Tests.xctest"
|
||||
BlueprintName = "AirgappedSigning_Tests"
|
||||
ReferencedContainer = "container:AirgappedSigning.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
|
||||
BuildableName = "AirgappedSigning_Example.app"
|
||||
BlueprintName = "AirgappedSigning_Example"
|
||||
ReferencedContainer = "container:AirgappedSigning.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
|
||||
BuildableName = "AirgappedSigning_Example.app"
|
||||
BlueprintName = "AirgappedSigning_Example"
|
||||
ReferencedContainer = "container:AirgappedSigning.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
|
||||
BuildableName = "AirgappedSigning_Example.app"
|
||||
BlueprintName = "AirgappedSigning_Example"
|
||||
ReferencedContainer = "container:AirgappedSigning.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
10
Example/AirgappedSigning.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
Example/AirgappedSigning.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:AirgappedSigning.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
34
Example/AirgappedSigning/AppDelegate.swift
Normal file
34
Example/AirgappedSigning/AppDelegate.swift
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// AirgappedSigning
|
||||
//
|
||||
// Created by Wolf McNally on 09/15/2018.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
35
Example/AirgappedSigning/Base.lproj/LaunchScreen.xib
Normal file
35
Example/AirgappedSigning/Base.lproj/LaunchScreen.xib
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="AirgappedSigning" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="139.5" width="440" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
30
Example/AirgappedSigning/Base.lproj/Main.storyboard
Normal file
30
Example/AirgappedSigning/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="ufC-wZ-h7g">
|
||||
<objects>
|
||||
<viewController id="vXZ-lx-hvc" customClass="ViewController" customModule="AirgappedSigning_Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@ -0,0 +1,53 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
39
Example/AirgappedSigning/Info.plist
Normal file
39
Example/AirgappedSigning/Info.plist
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
28
Example/AirgappedSigning/ViewController.swift
Normal file
28
Example/AirgappedSigning/ViewController.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// AirgappedSigning
|
||||
//
|
||||
// Created by Wolf McNally on 09/15/2018.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
class ViewController: UIViewController {
|
||||
}
|
||||
13
Example/Podfile
Normal file
13
Example/Podfile
Normal file
@ -0,0 +1,13 @@
|
||||
use_frameworks!
|
||||
|
||||
platform :ios, '12.0'
|
||||
|
||||
# pod 'Bitcoin', :path => '../../Bitcoin'
|
||||
|
||||
target 'AirgappedSigning_Example' do
|
||||
pod 'AirgappedSigning', :path => '../'
|
||||
|
||||
target 'AirgappedSigning_Tests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
81
Example/Podfile.lock
Normal file
81
Example/Podfile.lock
Normal file
@ -0,0 +1,81 @@
|
||||
PODS:
|
||||
- AirgappedSigning (0.1.0):
|
||||
- Bitcoin
|
||||
- NonEmpty
|
||||
- WolfCore
|
||||
- Bitcoin (0.5.1):
|
||||
- CBitcoin
|
||||
- WolfCore
|
||||
- CBitcoin (0.5.1)
|
||||
- ExtensibleEnumeratedName (2.0)
|
||||
- NonEmpty (0.2.0)
|
||||
- WolfConcurrency (3.0.2):
|
||||
- WolfFoundation
|
||||
- WolfNumerics
|
||||
- WolfCore (4.0.8):
|
||||
- ExtensibleEnumeratedName
|
||||
- WolfConcurrency
|
||||
- WolfFoundation
|
||||
- WolfNesting
|
||||
- WolfNumerics
|
||||
- WolfOSBridge
|
||||
- WolfPipe
|
||||
- WolfStrings
|
||||
- WolfWith
|
||||
- WolfFoundation (3.0.3):
|
||||
- WolfNumerics
|
||||
- WolfPipe
|
||||
- WolfNesting (2.0.1)
|
||||
- WolfNumerics (4.0)
|
||||
- WolfOSBridge (2.0.0)
|
||||
- WolfPipe (2.0.0)
|
||||
- WolfStrings (2.0.0):
|
||||
- ExtensibleEnumeratedName
|
||||
- WolfNumerics
|
||||
- WolfOSBridge
|
||||
- WolfPipe
|
||||
- WolfWith
|
||||
- WolfWith (2.0.1)
|
||||
|
||||
DEPENDENCIES:
|
||||
- AirgappedSigning (from `../`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- Bitcoin
|
||||
- CBitcoin
|
||||
- ExtensibleEnumeratedName
|
||||
- NonEmpty
|
||||
- WolfConcurrency
|
||||
- WolfCore
|
||||
- WolfFoundation
|
||||
- WolfNesting
|
||||
- WolfNumerics
|
||||
- WolfOSBridge
|
||||
- WolfPipe
|
||||
- WolfStrings
|
||||
- WolfWith
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
AirgappedSigning:
|
||||
:path: "../"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AirgappedSigning: 70ccc68e9502cac566b3b42935dc7f1c200d2378
|
||||
Bitcoin: 94763986cdecff4b05b89c84f0afd5439d53ba6b
|
||||
CBitcoin: 3f0f2e4e211aa10573940d8d9c9b0b0123ad24b5
|
||||
ExtensibleEnumeratedName: 50f2d256f6d56baecf681f6fbb6362343dcf885b
|
||||
NonEmpty: ffdc4086fbb2d7b977529a1b56bd6e7d4514ad76
|
||||
WolfConcurrency: 50458b6d801209f89e41d4bb9d57c80c65984770
|
||||
WolfCore: aaa510f76683e9f038e878d11356836eb135fd52
|
||||
WolfFoundation: c38312563289428f5f0396df9af43bc81918bc53
|
||||
WolfNesting: 891247e766da604f0e8124d85a158fe123ceb8d8
|
||||
WolfNumerics: 6a57756b668073414da8a6911b86781096aded37
|
||||
WolfOSBridge: e9260681790a7c89f725e134c0c1d4172d2d2dc9
|
||||
WolfPipe: 18ffb77a188263392893a62630defc2a5b92b4f3
|
||||
WolfStrings: edc63c08fbd1149ccbf5eca5020b13465084513b
|
||||
WolfWith: 2320a88a03a943df9ff1284c9cca10f86cb73c60
|
||||
|
||||
PODFILE CHECKSUM: cdec0639a121f10bcbb4c9ad550349d37a0d14c9
|
||||
|
||||
COCOAPODS: 1.7.0.beta.2
|
||||
24
Example/Tests/Info.plist
Normal file
24
Example/Tests/Info.plist
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
97
Example/Tests/Tests.swift
Normal file
97
Example/Tests/Tests.swift
Normal file
@ -0,0 +1,97 @@
|
||||
import XCTest
|
||||
import AirgappedSigning
|
||||
|
||||
class Tests: XCTestCase {
|
||||
func decodeDocument(from json: String) throws -> Document {
|
||||
let data = json.data(using: .utf8)!
|
||||
let document = try JSONDecoder().decode(Document.self, from: data)
|
||||
try document.check()
|
||||
return document
|
||||
}
|
||||
|
||||
func testThrowsOnNoContent() {
|
||||
let json = """
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
"""
|
||||
XCTAssertThrowsError( try decodeDocument(from: json) )
|
||||
}
|
||||
|
||||
func testThrowsOnNoHeader() {
|
||||
let json = """
|
||||
{
|
||||
"recoveryWords": {
|
||||
"name": "Rainy Day",
|
||||
"format": "BIP39",
|
||||
"words": ["panda", "diary", "marriage", "suffer", "basic", "glare", "surge", "auto", "scissors", "describe", "sell", "unique"]
|
||||
}
|
||||
}
|
||||
"""
|
||||
XCTAssertThrowsError( try decodeDocument(from: json) )
|
||||
}
|
||||
|
||||
func testThrowsOnMoreThanOneContent() {
|
||||
let json = """
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"recoveryWords": {
|
||||
"name": "Rainy Day",
|
||||
"format": "BIP39",
|
||||
"words": ["panda", "diary", "marriage", "suffer", "basic", "glare", "surge", "auto", "scissors", "describe", "sell", "unique"]
|
||||
},
|
||||
"knownReceiver": {
|
||||
"name": "Example",
|
||||
"asset": "BTC",
|
||||
"address": "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"
|
||||
}
|
||||
}
|
||||
"""
|
||||
XCTAssertThrowsError( try decodeDocument(from: json) )
|
||||
}
|
||||
|
||||
func testThrowsOnEmptyWords() {
|
||||
let json = """
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"recoveryWords": {
|
||||
"name": "Rainy Day",
|
||||
"format": "BIP39",
|
||||
"words": []
|
||||
}
|
||||
}
|
||||
"""
|
||||
XCTAssertThrowsError( try decodeDocument(from: json) )
|
||||
}
|
||||
|
||||
func test1() throws {
|
||||
let json = """
|
||||
{
|
||||
"header": {
|
||||
"format": "AirgappedSigning",
|
||||
"version": 1
|
||||
},
|
||||
"recoveryWords": {
|
||||
"name": "Rainy Day",
|
||||
"format": "BIP39",
|
||||
"words": ["panda", "diary", "marriage", "suffer", "basic", "glare", "surge", "auto", "scissors", "describe", "sell", "unique"]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
let data = json.data(using: .utf8)!
|
||||
|
||||
let decoded = try JSONDecoder().decode(AirgappedSigning.Document.self, from: data)
|
||||
|
||||
dump(decoded)
|
||||
}
|
||||
}
|
||||
19
LICENSE
Normal file
19
LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright © 2018 Wolf McNally <wolf@wolfmcnally.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
16
Package.swift
Normal file
16
Package.swift
Normal file
@ -0,0 +1,16 @@
|
||||
// swift-tools-version:5.0
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "AirgappedSigning",
|
||||
products: [
|
||||
.library(
|
||||
name: "AirgappedSigning",
|
||||
targets: ["AirgappedSigning"]),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "AirgappedSigning",
|
||||
dependencies: [])
|
||||
]
|
||||
)
|
||||
31
README.md
Normal file
31
README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# AirgappedSigning
|
||||
|
||||
[](https://travis-ci.org/wolfmcnally/AirgappedSigning)
|
||||
[](https://cocoapods.org/pods/AirgappedSigning)
|
||||
[](https://cocoapods.org/pods/AirgappedSigning)
|
||||
[](https://cocoapods.org/pods/AirgappedSigning)
|
||||
|
||||
## Example
|
||||
|
||||
To run the example project, clone the repo, and run `pod install` from the Example directory first.
|
||||
|
||||
## Requirements
|
||||
|
||||
Swift 4.2
|
||||
|
||||
## Installation
|
||||
|
||||
AirgappedSigning is available through [CocoaPods](https://cocoapods.org). To install
|
||||
it, simply add the following line to your Podfile:
|
||||
|
||||
```ruby
|
||||
pod 'AirgappedSigning'
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
Wolf McNally, wolf@wolfmcnally.com
|
||||
|
||||
## License
|
||||
|
||||
AirgappedSigning is available under the MIT license. See the LICENSE file for more info.
|
||||
0
Sources/AirgappedSigning/.gitkeep
Normal file
0
Sources/AirgappedSigning/.gitkeep
Normal file
35
Sources/AirgappedSigning/Account.swift
Normal file
35
Sources/AirgappedSigning/Account.swift
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// Account.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Account: Codable, Checked {
|
||||
public var name: String?
|
||||
public var asset: String
|
||||
public var hdPublicKey: String
|
||||
public var index: Int
|
||||
|
||||
public func check() throws {
|
||||
try checkName(name, context: "Account.name")
|
||||
try checkAsset(asset, context: "Account")
|
||||
try checkNotEmpty(hdPublicKey, context: "Account.hdPublicKey")
|
||||
try checkNotNegative(index, context: "Account.index")
|
||||
}
|
||||
}
|
||||
37
Sources/AirgappedSigning/AirgappedSigningError.swift
Normal file
37
Sources/AirgappedSigning/AirgappedSigningError.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// AirgappedSigningError.swift
|
||||
// AirgappedSigning
|
||||
//
|
||||
// Created by Wolf McNally on 9/15/18.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct AirgappedSigningError: Error, CustomStringConvertible {
|
||||
public let message: String
|
||||
|
||||
public init(_ message: String) {
|
||||
self.message = message
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return message
|
||||
}
|
||||
}
|
||||
68
Sources/AirgappedSigning/Checked.swift
Normal file
68
Sources/AirgappedSigning/Checked.swift
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// Checked.swift
|
||||
// AirgappedSigning
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol Checked {
|
||||
/// Performs second-level validation and throws if it fails.
|
||||
func check() throws
|
||||
}
|
||||
|
||||
func checkName(_ name: String?, context: String) throws {
|
||||
if let name = name {
|
||||
try checkNotEmpty(name, context: context)
|
||||
}
|
||||
}
|
||||
|
||||
func checkAsset(_ asset: String, context: String) throws {
|
||||
guard ["BTC", "BTCT"].contains(asset) else {
|
||||
throw AirgappedSigningError("\(context): Unsupported asset: \(asset).")
|
||||
}
|
||||
}
|
||||
|
||||
func checkNotEmpty(_ string: String, context: String) throws {
|
||||
guard !string.isEmpty else {
|
||||
throw AirgappedSigningError("\(context): Must be non-empty.")
|
||||
}
|
||||
}
|
||||
|
||||
func checkNotEmpty(_ data: Data, context: String) throws {
|
||||
guard !data.isEmpty else {
|
||||
throw AirgappedSigningError("\(context): Must be non-empty.")
|
||||
}
|
||||
}
|
||||
|
||||
func checkNotEmpty<C>(_ collection: C, context: String) throws where C: Collection {
|
||||
guard !collection.isEmpty else {
|
||||
throw AirgappedSigningError("\(context): Must be non-empty.")
|
||||
}
|
||||
}
|
||||
|
||||
func checkNotNegative<N: BinaryInteger>(_ n: N, context: String) throws {
|
||||
guard n >= 0 else {
|
||||
throw AirgappedSigningError("\(context): Must be non-negative.")
|
||||
}
|
||||
}
|
||||
|
||||
func checkPositive<N: BinaryInteger>(_ n: N, context: String) throws {
|
||||
guard n > 0 else {
|
||||
throw AirgappedSigningError("\(context): Must be positive.")
|
||||
}
|
||||
}
|
||||
42
Sources/AirgappedSigning/Document.swift
Normal file
42
Sources/AirgappedSigning/Document.swift
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// Document.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Document: Codable, Checked {
|
||||
public var header: Header
|
||||
|
||||
public var multiPart: MultiPart?
|
||||
public var recoveryWords: RecoveryWords?
|
||||
public var knownReceiver: KnownReceiver?
|
||||
public var account: Account?
|
||||
public var transaction: Transaction?
|
||||
|
||||
public func check() throws {
|
||||
try header.check()
|
||||
|
||||
let possibleContent: [Checked?] = [multiPart, recoveryWords, knownReceiver, account, transaction]
|
||||
let content = possibleContent.compactMap { $0 }
|
||||
guard content.count == 1 else {
|
||||
throw AirgappedSigningError("Document: Exactly one content type must be included. Got: \(content.count).")
|
||||
}
|
||||
try content.first!.check()
|
||||
}
|
||||
}
|
||||
37
Sources/AirgappedSigning/Header.swift
Normal file
37
Sources/AirgappedSigning/Header.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// Header.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Header: Codable, Checked {
|
||||
public var format: Format
|
||||
public var version: Version
|
||||
|
||||
public func check() throws {
|
||||
}
|
||||
|
||||
public enum Format: String, Codable {
|
||||
case AirgappedSigning
|
||||
}
|
||||
|
||||
public enum Version: Int, Codable {
|
||||
case v1 = 1
|
||||
}
|
||||
}
|
||||
33
Sources/AirgappedSigning/KnownReceiver.swift
Normal file
33
Sources/AirgappedSigning/KnownReceiver.swift
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// KnownReceiver.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct KnownReceiver: Codable, Checked {
|
||||
public var name: String?
|
||||
public var asset: String
|
||||
public var address: String
|
||||
|
||||
public func check() throws {
|
||||
try checkName(name, context: "KnownReceiver.name")
|
||||
try checkAsset(asset, context: "KnownReceiver")
|
||||
try checkNotEmpty(address, context: "KnownReceiver.address")
|
||||
}
|
||||
}
|
||||
34
Sources/AirgappedSigning/MultiPart.swift
Normal file
34
Sources/AirgappedSigning/MultiPart.swift
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// MultiPart.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct MultiPart: Codable, Checked {
|
||||
public var uid: UUID
|
||||
public var part: Int
|
||||
public var count: Int
|
||||
public var data: Data
|
||||
|
||||
public func check() throws {
|
||||
try checkNotNegative(part, context: "Multipart.part")
|
||||
try checkPositive(count, context: "Multipart.count")
|
||||
try checkNotEmpty(data, context: "Multipart.data")
|
||||
}
|
||||
}
|
||||
37
Sources/AirgappedSigning/RecoveryWords.swift
Normal file
37
Sources/AirgappedSigning/RecoveryWords.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// RecoveryWords.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import NonEmpty
|
||||
|
||||
public struct RecoveryWords: Codable, Checked {
|
||||
public var name: String?
|
||||
public var format: Format
|
||||
public var words: [String]
|
||||
|
||||
public func check() throws {
|
||||
try checkName(name, context: "RecoveryWords.name")
|
||||
try checkNotEmpty(words, context: "RecoveryWords.words")
|
||||
}
|
||||
|
||||
public enum Format: String, Codable {
|
||||
case BIP39
|
||||
}
|
||||
}
|
||||
98
Sources/AirgappedSigning/Transaction.swift
Normal file
98
Sources/AirgappedSigning/Transaction.swift
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// Transaction.swift
|
||||
// AirgappedSigning_Example
|
||||
//
|
||||
// Created by Wolf McNally on 4/23/19.
|
||||
//
|
||||
// Copyright © 2019 Blockchain Commons.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Transaction: Codable, Checked {
|
||||
public var uid: UUID
|
||||
public var asset: String?
|
||||
public var inputs: [Input]?
|
||||
public var outputs: [Output]?
|
||||
public var inputSignatures: [InputSignature]?
|
||||
|
||||
public func check() throws {
|
||||
if let asset = asset {
|
||||
try checkAsset(asset, context: "Transaction")
|
||||
}
|
||||
if let inputs = inputs {
|
||||
try checkNotEmpty(inputs, context: "Transaction.inputs")
|
||||
try inputs.forEach { try $0.check() }
|
||||
}
|
||||
if let outputs = outputs {
|
||||
try checkNotEmpty(outputs, context: "Transaction.outputs")
|
||||
try outputs.forEach { try $0.check() }
|
||||
}
|
||||
if let inputSignatures = inputSignatures {
|
||||
try checkNotEmpty(inputSignatures, context: "Transaction.inputSignatures")
|
||||
try inputSignatures.forEach { try $0.check() }
|
||||
}
|
||||
}
|
||||
|
||||
public struct Derivation: Codable, Checked {
|
||||
public var accountIndex: Int
|
||||
public var addressIndex: Int
|
||||
|
||||
public func check() throws {
|
||||
try checkNotNegative(accountIndex, context: "Derivation.accountIndex")
|
||||
try checkNotNegative(addressIndex, context: "Derivation.addressIndex")
|
||||
}
|
||||
}
|
||||
|
||||
public struct Input: Codable, Checked {
|
||||
public var uid: UUID
|
||||
public var txHash: String
|
||||
public var inputIndex: Int
|
||||
public var sender: String
|
||||
public var derivation: Derivation
|
||||
public var amount: UInt64
|
||||
|
||||
public func check() throws {
|
||||
try checkNotEmpty(txHash, context: "Input.txHash")
|
||||
try checkNotNegative(inputIndex, context: "Input.inputIndex")
|
||||
try checkNotEmpty(sender, context: "Input.sender")
|
||||
try derivation.check()
|
||||
try checkPositive(amount, context: "Input.amount")
|
||||
}
|
||||
}
|
||||
|
||||
public struct Output: Codable, Checked {
|
||||
public var uid: UUID
|
||||
public var receiver: String
|
||||
public var amount: UInt64
|
||||
public var derivation: Derivation?
|
||||
|
||||
public func check() throws {
|
||||
try checkNotEmpty(receiver, context: "Output.receiver")
|
||||
try checkPositive(amount, context: "Output.amount")
|
||||
try derivation?.check()
|
||||
}
|
||||
}
|
||||
|
||||
public struct InputSignature: Codable, Checked {
|
||||
public var uid: UUID
|
||||
public var ecPublicKey: Data
|
||||
public var ecSignature: Data
|
||||
|
||||
public func check() throws {
|
||||
try checkNotEmpty(ecPublicKey, context: "InputSignature.ecPublicKey")
|
||||
try checkNotEmpty(ecSignature, context: "InputSignature.ecSignature")
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user