Merge pull request #32 from keeshux/restore-pia-patches
Restore PIA patches
This commit is contained in:
commit
69e5921163
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project _will soon adhere_ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Restore support for PIA patches. [#32](https://github.com/keeshux/tunnelkit/pull/32)
|
||||
|
||||
## 1.1.1 (2018-10-10)
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -91,11 +91,12 @@ extension ViewController {
|
|||
var builder = TunnelKitProvider.ConfigurationBuilder(ca: ca)
|
||||
let socketType: TunnelKitProvider.SocketType = switchTCP.isOn ? .tcp : .udp
|
||||
builder.endpointProtocols = [TunnelKitProvider.EndpointProtocol(socketType, port)]
|
||||
builder.cipher = .aes128cbc
|
||||
builder.cipher = .aes256gcm
|
||||
builder.digest = .sha1
|
||||
builder.mtu = 1350
|
||||
builder.compressionFraming = .compLZO
|
||||
builder.renegotiatesAfterSeconds = nil
|
||||
builder.usesPIAPatches = true
|
||||
builder.shouldDebug = true
|
||||
builder.debugLogKey = "Log"
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
PODS:
|
||||
- OpenSSL-Apple (1.1.0i-v2)
|
||||
- SwiftyBeaver (1.6.1)
|
||||
- TunnelKit (1.1.0):
|
||||
- TunnelKit/AppExtension (= 1.1.0)
|
||||
- TunnelKit/Core (= 1.1.0)
|
||||
- TunnelKit/AppExtension (1.1.0):
|
||||
- TunnelKit (1.1.2):
|
||||
- TunnelKit/AppExtension (= 1.1.2)
|
||||
- TunnelKit/Core (= 1.1.2)
|
||||
- TunnelKit/AppExtension (1.1.2):
|
||||
- SwiftyBeaver
|
||||
- TunnelKit/Core
|
||||
- TunnelKit/Core (1.1.0):
|
||||
- TunnelKit/Core (1.1.2):
|
||||
- OpenSSL-Apple (~> 1.1.0h)
|
||||
- SwiftyBeaver
|
||||
|
||||
|
@ -26,7 +26,7 @@ EXTERNAL SOURCES:
|
|||
SPEC CHECKSUMS:
|
||||
OpenSSL-Apple: a93b8f2eec8783ff40d9a9304de180ab68bb647c
|
||||
SwiftyBeaver: ccfcdf85a04d429f1633f668650b0ce8020bda3a
|
||||
TunnelKit: 21af89c08aadfa81d25835a1faa46ddf12374772
|
||||
TunnelKit: 392e78dd45cded30a6f814200b8334c33901f677
|
||||
|
||||
PODFILE CHECKSUM: f66dfaaa92a8d04ab2743f3caeab0ac9f9f25859
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
0E3E0F212108A8CC00B371C1 /* SessionProxy+PushReply.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3E0F202108A8CC00B371C1 /* SessionProxy+PushReply.swift */; };
|
||||
0E3E0F222108A8CC00B371C1 /* SessionProxy+PushReply.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3E0F202108A8CC00B371C1 /* SessionProxy+PushReply.swift */; };
|
||||
0E58F1302138AC2F00A49F27 /* DNSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E58F12F2138AC2F00A49F27 /* DNSTests.swift */; };
|
||||
0E749F622178911D00BB2701 /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
||||
0E749F5F2178885500BB2701 /* SessionProxy+PIA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E749F5E2178885500BB2701 /* SessionProxy+PIA.swift */; };
|
||||
0E749F602178885500BB2701 /* SessionProxy+PIA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E749F5E2178885500BB2701 /* SessionProxy+PIA.swift */; };
|
||||
0E85A25A202CC5AF0059E9F9 /* AppExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E85A259202CC5AE0059E9F9 /* AppExtensionTests.swift */; };
|
||||
0E9379C91F819A4300CE91B6 /* TunnelKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E17D7F91F730D9F009EE129 /* TunnelKit.framework */; };
|
||||
0EB2B45320F0BB44004233D7 /* EncryptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB2B45220F0BB44004233D7 /* EncryptionTests.swift */; };
|
||||
|
@ -214,6 +217,8 @@
|
|||
0E58F12F2138AC2F00A49F27 /* DNSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSTests.swift; sourceTree = "<group>"; };
|
||||
0E6479DD212EAC96008E6888 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
0E6479E0212EACD6008E6888 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
0E749F612178911C00BB2701 /* pia-2048.pem */ = {isa = PBXFileReference; lastKnownFileType = text; path = "pia-2048.pem"; sourceTree = "<group>"; };
|
||||
0E749F5E2178885500BB2701 /* SessionProxy+PIA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+PIA.swift"; sourceTree = "<group>"; };
|
||||
0E85A259202CC5AE0059E9F9 /* AppExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppExtensionTests.swift; sourceTree = "<group>"; };
|
||||
0E85A25B202CCA3D0059E9F9 /* TunnelKitHost.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TunnelKitHost.entitlements; sourceTree = "<group>"; };
|
||||
0EB2B45220F0BB44004233D7 /* EncryptionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionTests.swift; sourceTree = "<group>"; };
|
||||
|
@ -340,6 +345,7 @@
|
|||
0EB2B45620F0BD16004233D7 /* RandomTests.swift */,
|
||||
0EB2B45C20F0BF41004233D7 /* RawPerformanceTests.swift */,
|
||||
0EB2B45A20F0BE4C004233D7 /* TestUtils.swift */,
|
||||
0E749F612178911C00BB2701 /* pia-2048.pem */,
|
||||
);
|
||||
path = TunnelKitTests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -472,6 +478,7 @@
|
|||
0ED9C8632138139000621BA3 /* SessionProxy+CompressionFraming.swift */,
|
||||
0E0C2124212ED29D008AB282 /* SessionProxy+Configuration.swift */,
|
||||
0EFEB42A2006D3C800F81029 /* SessionProxy+EncryptionBridge.swift */,
|
||||
0E749F5E2178885500BB2701 /* SessionProxy+PIA.swift */,
|
||||
0E3E0F202108A8CC00B371C1 /* SessionProxy+PushReply.swift */,
|
||||
0EFEB42B2006D3C800F81029 /* SessionProxy+SessionKey.swift */,
|
||||
0EFEB4442006D3C800F81029 /* TLSBox.h */,
|
||||
|
@ -719,6 +726,7 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0E749F622178911D00BB2701 /* pia-2048.pem in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -869,6 +877,7 @@
|
|||
0EC1BBA520D71190007C4C7B /* DNSResolver.swift in Sources */,
|
||||
0EFEB4AB200760EC00F81029 /* MemoryDestination.swift in Sources */,
|
||||
0EFEB4AE2007625E00F81029 /* Keychain.swift in Sources */,
|
||||
0E749F5F2178885500BB2701 /* SessionProxy+PIA.swift in Sources */,
|
||||
0EBBF3002085196000E36B40 /* NWTCPConnectionState+Description.swift in Sources */,
|
||||
0EFEB4622006D3C800F81029 /* SecureRandom.swift in Sources */,
|
||||
0EFEB45D2006D3C800F81029 /* CryptoBox.m in Sources */,
|
||||
|
@ -924,6 +933,7 @@
|
|||
0EFEB4B12007627700F81029 /* MemoryDestination.swift in Sources */,
|
||||
0EC1BBA620D712DE007C4C7B /* DNSResolver.swift in Sources */,
|
||||
0EFEB4A02006D7F300F81029 /* ReplayProtector.m in Sources */,
|
||||
0E749F602178885500BB2701 /* SessionProxy+PIA.swift in Sources */,
|
||||
0EFEB4992006D7F300F81029 /* SessionProxy.swift in Sources */,
|
||||
0EBBF3012085196000E36B40 /* NWTCPConnectionState+Description.swift in Sources */,
|
||||
0EFEB4962006D7F300F81029 /* ProtocolMacros.swift in Sources */,
|
||||
|
|
|
@ -146,6 +146,9 @@ extension TunnelKitProvider {
|
|||
/// The number of seconds after which a renegotiation is started. Set to `nil` to disable renegotiation (default).
|
||||
public var renegotiatesAfterSeconds: Int?
|
||||
|
||||
/// Server is patched for the PIA VPN provider.
|
||||
public var usesPIAPatches: Bool?
|
||||
|
||||
// MARK: Debugging
|
||||
|
||||
/// Enables debugging. If `true`, then `debugLogKey` is a mandatory field.
|
||||
|
@ -177,6 +180,7 @@ extension TunnelKitProvider {
|
|||
compressionFraming = .disabled
|
||||
keepAliveSeconds = nil
|
||||
renegotiatesAfterSeconds = nil
|
||||
usesPIAPatches = false
|
||||
shouldDebug = false
|
||||
debugLogKey = nil
|
||||
debugLogFormat = nil
|
||||
|
@ -232,6 +236,7 @@ extension TunnelKitProvider {
|
|||
}
|
||||
keepAliveSeconds = providerConfiguration[S.keepAlive] as? Int
|
||||
renegotiatesAfterSeconds = providerConfiguration[S.renegotiatesAfter] as? Int
|
||||
usesPIAPatches = providerConfiguration[S.usesPIAPatches] as? Bool ?? false
|
||||
|
||||
shouldDebug = providerConfiguration[S.debug] as? Bool ?? false
|
||||
if shouldDebug {
|
||||
|
@ -268,6 +273,7 @@ extension TunnelKitProvider {
|
|||
compressionFraming: compressionFraming,
|
||||
keepAliveSeconds: keepAliveSeconds,
|
||||
renegotiatesAfterSeconds: renegotiatesAfterSeconds,
|
||||
usesPIAPatches: usesPIAPatches,
|
||||
shouldDebug: shouldDebug,
|
||||
debugLogKey: shouldDebug ? debugLogKey : nil,
|
||||
debugLogFormat: shouldDebug ? debugLogFormat : nil
|
||||
|
@ -304,6 +310,8 @@ extension TunnelKitProvider {
|
|||
|
||||
static let renegotiatesAfter = "RenegotiatesAfter"
|
||||
|
||||
static let usesPIAPatches = "UsesPIAPatches"
|
||||
|
||||
static let debug = "Debug"
|
||||
|
||||
static let debugLogKey = "DebugLogKey"
|
||||
|
@ -347,6 +355,9 @@ extension TunnelKitProvider {
|
|||
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.renegotiatesAfterSeconds`
|
||||
public let renegotiatesAfterSeconds: Int?
|
||||
|
||||
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.usesPIAPatches`
|
||||
public let usesPIAPatches: Bool?
|
||||
|
||||
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.shouldDebug`
|
||||
public let shouldDebug: Bool
|
||||
|
||||
|
@ -428,6 +439,9 @@ extension TunnelKitProvider {
|
|||
if let renegotiatesAfterSeconds = renegotiatesAfterSeconds {
|
||||
dict[S.renegotiatesAfter] = renegotiatesAfterSeconds
|
||||
}
|
||||
if let usesPIAPatches = usesPIAPatches {
|
||||
dict[S.usesPIAPatches] = usesPIAPatches
|
||||
}
|
||||
if let debugLogKey = debugLogKey {
|
||||
dict[S.debugLogKey] = debugLogKey
|
||||
}
|
||||
|
@ -518,6 +532,7 @@ extension TunnelKitProvider.Configuration: Equatable {
|
|||
builder.compressionFraming = compressionFraming
|
||||
builder.keepAliveSeconds = keepAliveSeconds
|
||||
builder.renegotiatesAfterSeconds = renegotiatesAfterSeconds
|
||||
builder.usesPIAPatches = usesPIAPatches
|
||||
builder.shouldDebug = shouldDebug
|
||||
builder.debugLogKey = debugLogKey
|
||||
builder.debugLogFormat = debugLogFormat
|
||||
|
|
|
@ -234,6 +234,7 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
|
|||
if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds {
|
||||
sessionConfiguration.renegotiatesAfter = TimeInterval(renegotiatesAfterSeconds)
|
||||
}
|
||||
sessionConfiguration.usesPIAPatches = cfg.usesPIAPatches ?? false
|
||||
|
||||
let proxy: SessionProxy
|
||||
do {
|
||||
|
|
|
@ -162,6 +162,9 @@ extension SessionProxy {
|
|||
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
||||
public var renegotiatesAfter: TimeInterval?
|
||||
|
||||
/// Server is patched for the PIA VPN provider.
|
||||
public var usesPIAPatches: Bool
|
||||
|
||||
/// :nodoc:
|
||||
public init(caPath: String) {
|
||||
credentials = nil
|
||||
|
@ -173,6 +176,7 @@ extension SessionProxy {
|
|||
compressionFraming = .disabled
|
||||
keepAliveInterval = nil
|
||||
renegotiatesAfter = nil
|
||||
usesPIAPatches = false
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,7 +194,8 @@ extension SessionProxy {
|
|||
clientKeyPath: clientKeyPath,
|
||||
compressionFraming: compressionFraming,
|
||||
keepAliveInterval: keepAliveInterval,
|
||||
renegotiatesAfter: renegotiatesAfter
|
||||
renegotiatesAfter: renegotiatesAfter,
|
||||
usesPIAPatches: usesPIAPatches
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -224,5 +229,8 @@ extension SessionProxy {
|
|||
|
||||
/// - Seealso: `SessionProxy.ConfigurationBuilder.renegotiatesAfter`
|
||||
public let renegotiatesAfter: TimeInterval?
|
||||
|
||||
/// - Seealso: `SessionProxy.ConfigurationBuilder.usesPIAPatches`
|
||||
public let usesPIAPatches: Bool
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// SessionProxy+PIA.swift
|
||||
// TunnelKit
|
||||
//
|
||||
// Created by Davide De Rosa on 10/18/18.
|
||||
// Copyright (c) 2018 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/keeshux
|
||||
//
|
||||
// This file is part of TunnelKit.
|
||||
//
|
||||
// TunnelKit is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// TunnelKit is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// This file incorporates work covered by the following copyright and
|
||||
// permission notice:
|
||||
//
|
||||
// Copyright (c) 2018-Present Private Internet Access
|
||||
//
|
||||
// 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
|
||||
|
||||
extension SessionProxy {
|
||||
struct PIAHardReset {
|
||||
private static let obfuscationKeyLength = 3
|
||||
|
||||
private static let magic = "53eo0rk92gxic98p1asgl5auh59r1vp4lmry1e3chzi100qntd"
|
||||
|
||||
private static let encodedFormat = "\(magic)crypto\t%@|%@\tca\t%@"
|
||||
|
||||
private let caMd5Digest: String
|
||||
|
||||
private let cipherName: String
|
||||
|
||||
private let digestName: String
|
||||
|
||||
init(caMd5Digest: String, cipher: Cipher, digest: Digest) {
|
||||
self.caMd5Digest = caMd5Digest
|
||||
cipherName = cipher.rawValue.lowercased()
|
||||
digestName = digest.rawValue.lowercased()
|
||||
}
|
||||
|
||||
// Ruby: pia_settings
|
||||
func encodedData() throws -> Data {
|
||||
guard let plainData = String(format: PIAHardReset.encodedFormat, cipherName, digestName, caMd5Digest).data(using: .ascii) else {
|
||||
fatalError("Unable to encode string to ASCII")
|
||||
}
|
||||
let keyBytes = try SecureRandom.data(length: PIAHardReset.obfuscationKeyLength)
|
||||
|
||||
var encodedData = Data(keyBytes)
|
||||
for (i, b) in plainData.enumerated() {
|
||||
let keyChar = keyBytes[i % keyBytes.count]
|
||||
let xorredB = b ^ keyChar
|
||||
|
||||
encodedData.append(xorredB)
|
||||
}
|
||||
return encodedData
|
||||
}
|
||||
}
|
||||
}
|
|
@ -556,8 +556,22 @@ public class SessionProxy {
|
|||
keys[negotiationKeyIdx] = newKey
|
||||
log.debug("Negotiation key index is \(negotiationKeyIdx)")
|
||||
|
||||
let payload = hardResetPayload() ?? Data()
|
||||
negotiationKey.state = .hardReset
|
||||
enqueueControlPackets(code: .hardResetClientV2, key: UInt8(negotiationKeyIdx), payload: Data())
|
||||
enqueueControlPackets(code: .hardResetClientV2, key: UInt8(negotiationKeyIdx), payload: payload)
|
||||
}
|
||||
|
||||
private func hardResetPayload() -> Data? {
|
||||
guard !configuration.usesPIAPatches else {
|
||||
let caMD5 = TLSBox.md5(forCertificatePath: configuration.caPath)
|
||||
log.debug("CA MD5 is: \(caMD5)")
|
||||
return try? PIAHardReset(
|
||||
caMd5Digest: caMD5,
|
||||
cipher: configuration.cipher,
|
||||
digest: configuration.digest
|
||||
).encodedData()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ruby: soft_reset
|
||||
|
|
|
@ -51,6 +51,8 @@ extern NSString *const TLSBoxPeerVerificationErrorNotification;
|
|||
//
|
||||
@interface TLSBox : NSObject
|
||||
|
||||
+ (NSString *)md5ForCertificatePath:(NSString *)path;
|
||||
|
||||
- (instancetype)initWithCAPath:(NSString *)caPath
|
||||
clientCertificatePath:(nullable NSString *)clientCertificatePath
|
||||
clientKeyPath:(nullable NSString *)clientKeyPath;
|
||||
|
|
|
@ -75,6 +75,25 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
|||
|
||||
@implementation TLSBox
|
||||
|
||||
+ (NSString *)md5ForCertificatePath:(NSString *)path
|
||||
{
|
||||
const EVP_MD *alg = EVP_get_digestbyname("MD5");
|
||||
uint8_t md[16];
|
||||
unsigned int len;
|
||||
|
||||
FILE *pem = fopen([path cStringUsingEncoding:NSASCIIStringEncoding], "r");
|
||||
X509 *cert = PEM_read_X509(pem, NULL, NULL, NULL);
|
||||
X509_digest(cert, alg, md, &len);
|
||||
X509_free(cert);
|
||||
NSCAssert2(len == sizeof(md), @"Unexpected MD5 size (%d != %lu)", len, sizeof(md));
|
||||
|
||||
NSMutableString *hex = [[NSMutableString alloc] initWithCapacity:2 * sizeof(md)];
|
||||
for (int i = 0; i < sizeof(md); ++i) {
|
||||
[hex appendFormat:@"%02x", md[i]];
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
[NSException raise:NSInvalidArgumentException format:@"Use initWithCAPath:clientCertificatePath:clientKeyPath:"];
|
||||
|
|
|
@ -86,6 +86,14 @@ class EncryptionTests: XCTestCase {
|
|||
let decrypted = try! server.decrypter().decryptData(encrypted, extra: extra)
|
||||
XCTAssertEqual(plain, decrypted)
|
||||
}
|
||||
|
||||
func testCertificateMD5() {
|
||||
let path = Bundle(for: EncryptionTests.self).path(forResource: "pia-2048", ofType: "pem")!
|
||||
let md5 = TLSBox.md5(forCertificatePath: path)
|
||||
let exp = "e2fccccaba712ccc68449b1c56427ac1"
|
||||
print(md5)
|
||||
XCTAssertEqual(md5, exp)
|
||||
}
|
||||
|
||||
private func clientServer(_ c: String?, _ d: String?) -> (CryptoBox, CryptoBox) {
|
||||
let client = CryptoBox(cipherAlgorithm: c, digestAlgorithm: d)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV
|
||||
BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu
|
||||
dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx
|
||||
IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB
|
||||
FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1
|
||||
MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
|
||||
EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg
|
||||
QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE
|
||||
AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50
|
||||
ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy
|
||||
bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD
|
||||
L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX
|
||||
lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp
|
||||
cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/
|
||||
8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB
|
||||
/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC
|
||||
OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL
|
||||
y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO
|
||||
sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM
|
||||
b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G
|
||||
A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg
|
||||
SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz
|
||||
czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j
|
||||
b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn
|
||||
a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU
|
||||
ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3
|
||||
7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC
|
||||
GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz
|
||||
1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt
|
||||
YDQ8z9v+DMO6iwyIDRiU
|
||||
-----END CERTIFICATE-----
|
||||
|
Loading…
Reference in New Issue