Initial commit
This commit is contained in:
commit
74347fa8d6
4 changed files with 92 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
20
Package.swift
Normal file
20
Package.swift
Normal file
|
@ -0,0 +1,20 @@
|
|||
// swift-tools-version:5.5
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "SwiftHawk",
|
||||
platforms: [
|
||||
.macOS(.v10_15),
|
||||
.tvOS(.v13),
|
||||
.watchOS(.v6),
|
||||
.iOS(.v13)
|
||||
],
|
||||
products: [
|
||||
.library(name: "SwiftHawk", targets: ["SwiftHawk"]),
|
||||
],
|
||||
targets: [
|
||||
.target(name: "SwiftHawk", dependencies: []),
|
||||
]
|
||||
)
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# SwiftHawk
|
||||
|
||||
[Hawk](https://github.com/mozilla/hawk) signature implementation for `URLRequest`
|
62
Sources/SwiftHawk/SwiftHawk.swift
Normal file
62
Sources/SwiftHawk/SwiftHawk.swift
Normal file
|
@ -0,0 +1,62 @@
|
|||
import Foundation
|
||||
import CryptoKit
|
||||
|
||||
public struct HawkCredentials {
|
||||
public var id: String
|
||||
public var key: SymmetricKey
|
||||
|
||||
public init(id: String, key: SymmetricKey) {
|
||||
self.id = id
|
||||
self.key = key
|
||||
}
|
||||
|
||||
public init(id: String, key: String) {
|
||||
self.init(id: id, key: SymmetricKey(data: Data(key.utf8)))
|
||||
}
|
||||
}
|
||||
|
||||
public extension URLRequest {
|
||||
mutating func sign<H: HashFunction>(credentials: HawkCredentials, hash: H.Type) {
|
||||
guard let url = url else { return }
|
||||
|
||||
let nonce = makeNonce()
|
||||
let timestamp = Int(Date().timeIntervalSince1970)
|
||||
|
||||
var path = url.path
|
||||
if let query = url.query {
|
||||
path += "?\(query)"
|
||||
}
|
||||
|
||||
let string = "hawk.1.header\n\(timestamp)\n\(nonce)\n\(httpMethod?.uppercased() ?? "GET")\n\(path)\n\(url.host ?? "")\n\(port)\n\n\n"
|
||||
|
||||
var hash = HMAC<H>(key: credentials.key)
|
||||
hash.update(data: Data(string.utf8))
|
||||
let signature = Data(hash.finalize()).base64EncodedString(options: [])
|
||||
|
||||
let header = "Hawk id=\"\(credentials.id)\", ts=\"\(timestamp)\", nonce=\"\(nonce)\", mac=\"\(signature)\""
|
||||
|
||||
addValue(header, forHTTPHeaderField: "Authorization")
|
||||
}
|
||||
|
||||
mutating func sign(credentials: HawkCredentials) {
|
||||
self.sign(credentials: credentials, hash: SHA256.self)
|
||||
}
|
||||
|
||||
var port: Int {
|
||||
if let port = url?.port {
|
||||
return port
|
||||
}
|
||||
|
||||
switch url?.scheme {
|
||||
case "http": return 80
|
||||
case "https": return 443
|
||||
default: return 0
|
||||
}
|
||||
}
|
||||
|
||||
func makeNonce() -> String {
|
||||
SymmetricKey(size: .init(bitCount: 48)).withUnsafeBytes { ptr in
|
||||
Data(ptr).base64EncodedString(options: [])
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue