1
+ //
2
+ // PeerID.swift
3
+ //
4
+ //
5
+ // Created by Brandon Toms on 5/1/22.
6
+ //
1
7
8
+ import LibP2PCrypto
2
9
import Foundation
3
10
import Multihash
4
- import Multibase
5
11
import CID
6
- import LibP2PCrypto
7
12
8
13
/// - Reference: https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#how-keys-are-encoded-and-messages-signed
9
14
public class PeerID {
@@ -103,178 +108,6 @@ public class PeerID {
103
108
self . keyPair = nil
104
109
}
105
110
106
- /// Inits a `PeerID` from a marshaled `PeerID` string
107
- /// - Note: `base` can be left `nil` if the marshaledPeerID String is `Multibase` compliant (includes the multibase prefix) otherwise, you must specify the ecoded base of the string...
108
- public convenience init ( marshaledPeerID: String , base: BaseEncoding ? = nil ) throws {
109
- let marshaledData : Data
110
- if let base = base {
111
- marshaledData = try BaseEncoding . decode ( marshaledPeerID, as: base) . data
112
- } else {
113
- marshaledData = try BaseEncoding . decode ( marshaledPeerID) . data
114
- }
115
- try self . init ( marshaledPeerID: marshaledData)
116
- }
117
-
118
- /// Inits a `PeerID` from a marshaled `PeerID`
119
- public convenience init ( marshaledPeerID data: Data ) throws {
120
- // Attampt to instantiate a PeerIdProto with the raw, marshaled, data
121
- let protoPeerID = try PeerIdProto ( contiguousBytes: data)
122
-
123
- //print(protoPeerID.id.asString(base: .base64))
124
- //print("Has PubKey: \(protoPeerID.hasPubKey)")
125
- //print(protoPeerID.pubKey.asString(base: .base64))
126
- //print("Has PrivKey: \(protoPeerID.hasPrivKey)")
127
- //print(protoPeerID.privKey.asString(base: .base64))
128
-
129
- // Enusre the Marshaled data included at least a public key (is this necessary, would we ever need to unmarshal an ID only?)
130
- guard protoPeerID. hasPubKey || protoPeerID. hasPrivKey else {
131
- throw NSError ( domain: " No Public or Private Key Found in marshaled data " , code: 0 , userInfo: nil )
132
- }
133
-
134
- // If we have a private key, attempt to instantiate the PeerID via the private key, otherwise, try the public key...
135
- if protoPeerID. hasPrivKey {
136
- try self . init ( marshaledPrivateKey: protoPeerID. privKey)
137
- } else if protoPeerID. hasPubKey {
138
- try self . init ( marshaledPublicKey: protoPeerID. pubKey)
139
- } else {
140
- throw NSError ( domain: " No Public or Private Key Found in marshaled data " , code: 0 , userInfo: nil )
141
- }
142
- }
143
-
144
- /// Inits a `PeerID` from a marshaled public key string
145
- public convenience init ( marshaledPublicKey str: String , base: BaseEncoding ) throws {
146
- try self . init ( keyPair: LibP2PCrypto . Keys. KeyPair ( marshaledPublicKey: str, base: base) )
147
- }
148
-
149
- /// Inits a `PeerID` from a marshaled public key
150
- public convenience init ( marshaledPublicKey key: Data ) throws {
151
- try self . init ( keyPair: LibP2PCrypto . Keys. KeyPair ( marshaledPublicKey: key) )
152
- }
153
-
154
- /// Inits a `PeerID` from a marshaled private key string
155
- public convenience init ( marshaledPrivateKey str: String , base: BaseEncoding ) throws {
156
- try self . init ( keyPair: LibP2PCrypto . Keys. KeyPair ( marshaledPrivateKey: str, base: base) )
157
- }
158
-
159
- /// Inits a `PeerID` from a marshaled private key
160
- public convenience init ( marshaledPrivateKey data: Data ) throws {
161
- try self . init ( keyPair: LibP2PCrypto . Keys. KeyPair ( marshaledPrivateKey: data) )
162
- }
163
-
164
- /// An Internal PeerID struct to facilitate JSON Encoding and Decoding
165
- internal struct PeerIDJSON : Codable {
166
- /// base58 encoded string
167
- let id : String
168
- /// base64 encoded publicKey protobuf
169
- let pubKey : String ?
170
- /// base64 encoded privateKey protobuf
171
- let privKey : String ?
172
- }
173
-
174
- /// Initialize a PeerID from JSON data
175
- ///
176
- /// Expects a JSON object of the form
177
- /// ```
178
- /// {
179
- /// obj.id: String - The multihash encoded in base58
180
- /// obj.pubKey: String? - The public key in protobuf format, encoded in 'base64'
181
- /// obj.privKey: String? - The private key in protobuf format, encoded in 'base64'
182
- /// }
183
- /// ```
184
- public convenience init ( fromJSON json: Data ) throws {
185
- let data = try JSONDecoder ( ) . decode ( PeerIDJSON . self, from: json)
186
-
187
- if data. privKey == nil && data. pubKey == nil {
188
- /// Only ID Present...
189
- try self . init ( fromBytesID: Multihash ( b58String: data. id) . value)
190
- } else if data. privKey == nil , let pubKey = data. pubKey {
191
- /// Only Public Key and ID Present, lets init via the public key and derive the ID
192
- /// TODO: Compare the provided ID and the Derived ID and throw an error if they dont match...
193
- try self . init ( marshaledPublicKey: pubKey, base: . base64)
194
- } else if let privKey = data. privKey {
195
- /// Private Key was provided. Lets init via the private key and derive both the public key and the ID
196
- /// TODO: Compare the provided publicKey and ID to the ones derived from the private key and throw an error if they don't match...
197
- try self . init ( marshaledPrivateKey: privKey, base: . base64)
198
- } else {
199
- throw NSError ( domain: " Failed to init PeerID from json " , code: 0 , userInfo: nil )
200
- }
201
- }
202
-
203
- /// Exports our PeerID as a JSON object
204
- ///
205
- /// Returns a JSON object of the form
206
- /// ```
207
- /// {
208
- /// obj.id: String - The multihash encoded in base58
209
- /// obj.pubKey: String? - The public key in protobuf format, encoded in 'base64'
210
- /// obj.privKey: String? - The private key in protobuf format, encoded in 'base64'
211
- /// }
212
- /// ```
213
- public func toJSON( includingPrivateKey: Bool = false ) throws -> Data {
214
- let pidJSON = PeerIDJSON (
215
- id: self . b58String,
216
- pubKey: try ? self . keyPair? . publicKey. marshal ( ) . asString ( base: . base64) ,
217
- privKey: includingPrivateKey ? try ? self . keyPair? . privateKey? . marshal ( ) . asString ( base: . base64) : nil
218
- )
219
-
220
- return try JSONEncoder ( ) . encode ( pidJSON)
221
- }
222
-
223
- public func toJSONString( includingPrivateKey: Bool = false ) throws -> String ? {
224
- return try String ( data: self . toJSON ( ) , encoding: . utf8)
225
- }
226
-
227
-
228
- // private static func computeDigest(pubKey:SecKey) throws -> [UInt8] {
229
- // let bytes = try pubKey.rawRepresentation()
230
- // return try self.computeDigest(rawPubKey: bytes)
231
- // }
232
- //
233
- // /// - Note: We need to marshal the raw public key before multihashing it....
234
- // private static func computeDigest(rawPubKey bytes:Data) throws -> [UInt8] {
235
- // let marshaled = try LibP2PCrypto.Keys.marshalPublicKey(raw: bytes, keyType: .RSA(bits: .B1024))
236
- // //print(marshaled.asString(base: .base64Pad))
237
- // if marshaled.count <= 42 {
238
- // return try Multihash(raw: marshaled, hashedWith: .identity).value
239
- // } else {
240
- // //let mh = try Multihash(raw: bytes, hashedWith: .sha2_256)
241
- // //print("Value: \(mh.value.asString(base: .base16))")
242
- // //print("Hex: \(mh.hexString)")
243
- // //print("Digest: \(mh.digest?.asString(base: .base16) ?? "NIL")")
244
- // return try Multihash(raw: marshaled, hashedWith: .sha2_256).value //pubKey.hash()
245
- // }
246
- // }
247
-
248
-
249
- /// Returns a protocol-buffers encoded version of the id, public key and, if `includingPrivateKey` is set to `true`, the private key.
250
- public func marshal( includingPrivateKey: Bool = false ) throws -> [ UInt8 ] {
251
- var pid = PeerIdProto ( )
252
- pid. id = Data ( self . id)
253
- pid. pubKey = try self . keyPair? . publicKey. marshal ( ) ?? Data ( )
254
- if includingPrivateKey, let privKey = self . keyPair? . privateKey {
255
- pid. privKey = try privKey. marshal ( )
256
- }
257
- return try pid. serializedData ( ) . bytes
258
- }
259
-
260
- public func marshalPrivateKey( ) throws -> [ UInt8 ] {
261
- guard let privKey = self . keyPair? . privateKey else {
262
- throw NSError ( domain: " This PeerID doesn't have a Private Key to Marshal " , code: 0 , userInfo: nil )
263
- }
264
- return try privKey. marshal ( ) . bytes
265
- }
266
-
267
- public func marshalPublicKey( ) throws -> [ UInt8 ] {
268
- guard let pubKey = self . keyPair? . publicKey else {
269
- throw NSError ( domain: " This PeerID doesn't have a Public Key to Marshal " , code: 0 , userInfo: nil )
270
- }
271
- return try pubKey. marshal ( ) . bytes
272
- }
273
-
274
- // public func marshalPublicKeyAsProtobuf() throws -> LibP2PCrypto.PublicKey {
275
- //
276
- // }
277
-
278
111
/// Returns the PeerID's id as a self-describing CIDv1 in Base32 (RFC 0001)
279
112
/// return self-describing String representation
280
113
/// in default format from RFC 0001: https://github.com/libp2p/specs/pull/209
@@ -292,31 +125,11 @@ public class PeerID {
292
125
private func toBase64Pad( _ buf: [ UInt8 ] ) -> String {
293
126
buf. asString ( base: . base64Pad)
294
127
}
295
-
296
- // Signs data using this PeerID's private key. This signature can then be verified by a remote peer using this PeerID's public key
297
- public func signature( for msg: Data ) throws -> Data {
298
- guard let priv = keyPair? . privateKey else {
299
- throw NSError ( domain: " A private key is required for generating signature and this PeerID doesn't contain a private key. " , code: 0 , userInfo: nil )
300
- }
301
-
302
- return try priv. sign ( message: msg)
303
- }
304
-
305
- // Using this PeerID's public key, this method checks to see if the signature data was in fact signed by this peer and is a valid signature for the expected data
306
- public func isValidSignature( _ signature: Data , for expectedData: Data ) throws -> Bool {
307
- guard let pub = keyPair? . publicKey else {
308
- throw NSError ( domain: " A public key is required for verifying signatures and this PeerID doesn't contain a public key. " , code: 0 , userInfo: nil )
309
- }
310
-
311
- return try pub. verify ( signature: signature, for: expectedData)
312
- }
313
128
}
314
129
315
130
extension PeerID : CustomStringConvertible {
316
131
public var description : String {
317
132
let pid = self . b58String
318
- // All sha256 nodes start with Qm
319
- // We can skip the Qm to make the peer.ID more useful
320
133
var skip = 0
321
134
if pid. hasPrefix ( " Qm " ) {
322
135
skip = 2
@@ -328,8 +141,6 @@ extension PeerID:CustomStringConvertible {
328
141
329
142
public var shortDescription : String {
330
143
let pid = self . b58String
331
- // All sha256 nodes start with Qm
332
- // We can skip the Qm to make the peer.ID more useful
333
144
if pid. hasPrefix ( " Qm " ) {
334
145
return String ( pid. dropFirst ( 2 ) . prefix ( 6 ) )
335
146
} else if pid. hasPrefix ( " 12D3KooW " ) {
@@ -355,17 +166,6 @@ private extension Array where Element == UInt8 {
355
166
}
356
167
}
357
168
358
- extension PeerID : Equatable {
359
- public static func == ( lhs: PeerID , rhs: PeerID ) -> Bool {
360
- lhs. id == rhs. id
361
- }
362
- public static func == ( lhs: [ UInt8 ] , rhs: PeerID ) -> Bool {
363
- lhs == rhs. id
364
- }
365
- public static func == ( lhs: Data , rhs: PeerID ) -> Bool {
366
- lhs. bytes == rhs. id
367
- }
368
- }
369
169
//public func computeDigest(rawPubKey:Data) -> Data {
370
170
// if rawPubKey.count <= 42 {
371
171
// return Multihash(raw: rawPubKey, hashedWith: .identity)
0 commit comments