Skip to content

Commit

Permalink
copy jwt lib, because this removed
Browse files Browse the repository at this point in the history
  • Loading branch information
buhe committed Sep 29, 2023
1 parent 4d7a814 commit 0688286
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 12 deletions.
9 changes: 0 additions & 9 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@
"version" : "1.1.1"
}
},
{
"identity" : "jwt",
"kind" : "remoteSourceControl",
"location" : "https://github.com/nextster/JWT",
"state" : {
"revision" : "a795848495c1e2a4aa6fe9ec8680b2a8ef7fb8ef",
"version" : "1.0.1"
}
},
{
"identity" : "keychainaccess",
"kind" : "remoteSourceControl",
Expand Down
2 changes: 0 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ let package = Package(
.package(url: "https://github.com/drmohundro/SWXMLHash", .upToNextMajor(from: "7.0.2")),
.package(url: "https://github.com/scinfu/SwiftSoup", .upToNextMajor(from: "2.6.1")),
.package(url: "https://github.com/swift-server/async-http-client", .upToNextMajor(from: "1.18.0")),
.package(url: "https://github.com/nextster/JWT", .upToNextMajor(from: "1.0.1")),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
Expand All @@ -35,7 +34,6 @@ let package = Package(
.product(name: "SwiftyJSON", package: "SwiftyJSON"),
.product(name: "SWXMLHash", package: "SWXMLHash"),
.product(name: "SwiftSoup", package: "SwiftSoup"),
.product(name: "JWT", package: "JWT"),
]

),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import AsyncHTTPClient
import Foundation
import NIOPosix
import JWT

struct ChatGLMMessage: Codable {
let role: String
Expand Down
58 changes: 58 additions & 0 deletions Sources/LangChain/utilities/jwt/Cryptor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation
import CommonCrypto

class Cryptor {

static func hmac(string: String, algorithm: Algorithm, key: String) -> String? {
guard let key = key.data(using: .utf8) else { return nil }
guard let string = string.data(using: .utf8) else { return nil }

let context = UnsafeMutablePointer<CCHmacContext>.allocate(capacity: 1)
defer { context.deallocate() }

key.withUnsafeBytes { (buffer: UnsafePointer<UInt8>) in
CCHmacInit(context, algorithm.HMACAlgorithm, buffer, size_t(key.count))
}

string.withUnsafeBytes { (buffer: UnsafePointer<UInt8>) in
CCHmacUpdate(context, buffer, size_t(string.count))
}

var hmac = Array<UInt8>(repeating: 0, count: Int(algorithm.digestLength))
CCHmacFinal(context, &hmac)

return Data(hmac).base64URLEncodedString()
}

enum Algorithm {
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512

var HMACAlgorithm: CCHmacAlgorithm {
var result: Int = 0
switch self {
case .MD5: result = kCCHmacAlgMD5
case .SHA1: result = kCCHmacAlgSHA1
case .SHA224: result = kCCHmacAlgSHA224
case .SHA256: result = kCCHmacAlgSHA256
case .SHA384: result = kCCHmacAlgSHA384
case .SHA512: result = kCCHmacAlgSHA512
}
return CCHmacAlgorithm(result)
}

var digestLength: Int {
var result: Int32 = 0
switch self {
case .MD5: result = CC_MD5_DIGEST_LENGTH
case .SHA1: result = CC_SHA1_DIGEST_LENGTH
case .SHA224: result = CC_SHA224_DIGEST_LENGTH
case .SHA256: result = CC_SHA256_DIGEST_LENGTH
case .SHA384: result = CC_SHA384_DIGEST_LENGTH
case .SHA512: result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
}


56 changes: 56 additions & 0 deletions Sources/LangChain/utilities/jwt/Extensions/String.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Foundation
/// Extension for making base64 representations of `Data` safe for
/// transmitting via URL query parameters
extension Data {

/// Instantiates data by decoding a base64url string into base64
///
/// - Parameter string: A base64url encoded string
init?(base64URLEncoded string: String) {
self.init(base64Encoded: string.toggleBase64URLSafe(on: false))
}

/// Encodes the string into a base64url safe representation
///
/// - Returns: A string that is base64 encoded but made safe for passing
/// in as a query parameter into a URL string
func base64URLEncodedString() -> String {
return self.base64EncodedString().toggleBase64URLSafe(on: true)
}

}

extension String {

var base64String: String? {
return data(using: .utf8)?.base64EncodedString()
}

var base64UrlString: String? {
return data(using: .utf8)?.base64URLEncodedString()
}

/// Encodes or decodes into a base64url safe representation
///
/// - Parameter on: Whether or not the string should be made safe for URL strings
/// - Returns: if `on`, then a base64url string; if `off` then a base64 string
func toggleBase64URLSafe(on: Bool) -> String {
if on {
// Make base64 string safe for passing into URL query params
let base64url = self.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "=", with: "")
return base64url
} else {
// Return to base64 encoding
var base64 = self.replacingOccurrences(of: "_", with: "/")
.replacingOccurrences(of: "-", with: "+")
// Add any necessary padding with `=`
if base64.count % 4 != 0 {
base64.append(String(repeating: "=", count: 4 - base64.count % 4))
}
return base64
}
}

}
121 changes: 121 additions & 0 deletions Sources/LangChain/utilities/jwt/JWT.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import Foundation

public class JWT {

public init(alg: JWT.Algorithm = .HS256, secret: String = "") {
self.alg = alg
self.header["alg"] = alg.rawValue
self.header["typ"] = "JWT"
self.secret = secret
}

public enum Algorithm: String {
case HS256
case HS384
case HS512

var forCryptor: Cryptor.Algorithm {
switch self {
case .HS256: return .SHA256
case .HS384: return .SHA384
case .HS512: return .SHA512
}
}
}
var alg: Algorithm

public var header: [String: String] = [:]
public var payload: [String: Any] = [:]
public var secret: String

public var subject: String? { return payload["sub"] as? String }
public var identifier: String? { return payload["jti"] as? String }
public var issuer: String? { return payload["iss"] as? String }

public var notValidBefore: Date? {
if let interval = payload["nbf"] as? TimeInterval {
return Date(timeIntervalSince1970: interval)
}
return nil
}
public var issuedAt: Date? {
if let interval = payload["iat"] as? TimeInterval {
return Date(timeIntervalSince1970: interval)
}
return nil
}
public var expiresAt: Date? {
if let interval = payload["exp"] as? TimeInterval {
return Date(timeIntervalSince1970: interval)
}
return nil
}

public var isExpired: Bool? {
guard let expireDate = expiresAt else { return nil }
return expireDate.compare(Date()) != .orderedDescending ? true : false}

public var token: String? {
do {
let headerString = try JSONSerialization.data(withJSONObject: header, options: []).base64URLEncodedString()
let payloadString = try JSONSerialization.data(withJSONObject: payload, options: []).base64URLEncodedString()

let rawSign = "\(headerString).\(payloadString)"

if let sign = Cryptor.hmac(string: rawSign, algorithm: alg.forCryptor, key: secret) {
return "\(rawSign).\(sign)"
} else {
print("JWT: Can't compute sign.")
return nil
}
} catch {
print(error.localizedDescription)
return nil
}
}
}

//MARK: - Token decoding
extension JWT {
public convenience init?(token: String) {
let elements = token.split(separator: ".").map({String($0)})
guard
elements.count == 3 else {
print("JWT: Wrong format!")
return nil
}

guard let headerData = Data(base64URLEncoded: elements[0]),
let payloadData = Data(base64URLEncoded: elements[1]) else {
print("JWT: Wrong format!")
print("Failed to parse header/payload.")
return nil
}

do {
guard let header = try JSONSerialization.jsonObject(with: headerData, options: []) as? [String: String],
let payload = try JSONSerialization.jsonObject(with: payloadData, options: []) as? [String: Any]
else {
print("JWT: Failed to parse header/payload.")
return nil
}

guard let algString = header["alg"] else {
print("JWT: Can't define algorithm.")
return nil
}
guard let alg = Algorithm(rawValue: algString) else {
print("JWT: Alghoritm doesn't support.")
return nil
}

self.init(alg: alg, secret: "")
self.header = header
self.payload = payload

} catch {
print(error.localizedDescription)
return nil
}
}
}

0 comments on commit 0688286

Please sign in to comment.