Support Steam OTP (#505)
This commit is contained in:
parent
06d2ef1d09
commit
f2ab400f4b
8 changed files with 85 additions and 34 deletions
|
|
@ -72,7 +72,6 @@
|
|||
30A3001826DA6974002A734E /* SwiftyUserDefaults in Frameworks */ = {isa = PBXBuildFile; productRef = 30A3001726DA6974002A734E /* SwiftyUserDefaults */; };
|
||||
30A3001A26DA697C002A734E /* SwiftyUserDefaults in Frameworks */ = {isa = PBXBuildFile; productRef = 30A3001926DA697C002A734E /* SwiftyUserDefaults */; };
|
||||
30A3001C26DA91BF002A734E /* SwiftyUserDefaults in Frameworks */ = {isa = PBXBuildFile; productRef = 30A3001B26DA91BF002A734E /* SwiftyUserDefaults */; };
|
||||
30A3001E26DA91C4002A734E /* OneTimePassword in Frameworks */ = {isa = PBXBuildFile; productRef = 30A3001D26DA91C4002A734E /* OneTimePassword */; };
|
||||
30A3002026DA91D7002A734E /* Base32 in Frameworks */ = {isa = PBXBuildFile; productRef = 30A3001F26DA91D7002A734E /* Base32 */; };
|
||||
30A69948240EED5E00B7D967 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A69947240EED5E00B7D967 /* IntentHandler.swift */; };
|
||||
30A86F95230F237000F821A4 /* CryptoFrameworkTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A86F94230F237000F821A4 /* CryptoFrameworkTest.swift */; };
|
||||
|
|
@ -108,7 +107,9 @@
|
|||
556EC3D922335D2800934F9C /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 30BF5ED521ED2434000E4154 /* Localizable.stringsdict */; };
|
||||
556EC3DA22335D3400934F9C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 30C25DBF21F3599E00BB27BB /* InfoPlist.strings */; };
|
||||
556EC3DB22335D3D00934F9C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 30C25DBF21F3599E00BB27BB /* InfoPlist.strings */; };
|
||||
9A17C06726DDAAE400C23FAB /* OneTimePassword in Frameworks */ = {isa = PBXBuildFile; productRef = 9A17C06626DDAAE400C23FAB /* OneTimePassword */; };
|
||||
9A1D1CE526E5D1CE0052028E /* OneTimePassword in Frameworks */ = {isa = PBXBuildFile; productRef = 9A1D1CE426E5D1CE0052028E /* OneTimePassword */; };
|
||||
9A1D1CE726E5D2230052028E /* OneTimePassword in Frameworks */ = {isa = PBXBuildFile; productRef = 9A1D1CE626E5D2230052028E /* OneTimePassword */; };
|
||||
9A1F47FA26E5CF4B000C0E01 /* OneTimePassword in Frameworks */ = {isa = PBXBuildFile; productRef = 9A1F47F926E5CF4B000C0E01 /* OneTimePassword */; };
|
||||
9A55C158259E785600FA8FD9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC917BDD1E2E8231000FDF54 /* Assets.xcassets */; };
|
||||
9A55C15F259E785700FA8FD9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC917BDD1E2E8231000FDF54 /* Assets.xcassets */; };
|
||||
9A55C185259E8C5600FA8FD9 /* PasswordsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A55C184259E8C5600FA8FD9 /* PasswordsViewController.swift */; };
|
||||
|
|
@ -127,7 +128,6 @@
|
|||
9A8F9ECC259ECB410027CE15 /* PasswordSelectionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A8F9ECB259ECB410027CE15 /* PasswordSelectionDelegate.swift */; };
|
||||
9A8F9F4025A1A91F0027CE15 /* CredentialProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A8F9F3F25A1A91F0027CE15 /* CredentialProvider.swift */; };
|
||||
9A996C5326DDF61F00A4485D /* Base32 in Frameworks */ = {isa = PBXBuildFile; productRef = 9A996C5226DDF61F00A4485D /* Base32 */; };
|
||||
9A996C5526DDF62300A4485D /* OneTimePassword in Frameworks */ = {isa = PBXBuildFile; productRef = 9A996C5426DDF62300A4485D /* OneTimePassword */; };
|
||||
9A996C5726DDF65900A4485D /* Base32 in Frameworks */ = {isa = PBXBuildFile; productRef = 9A996C5626DDF65900A4485D /* Base32 */; };
|
||||
9A996C5826DEB0D100A4485D /* passKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A26075781EEC6F34005DB03E /* passKit.framework */; };
|
||||
9A996C5926DEB0D200A4485D /* passKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A26075781EEC6F34005DB03E /* passKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
|
|
@ -511,7 +511,7 @@
|
|||
9ADAB21D26DDA52400900F10 /* Gopenpgp.xcframework in Frameworks */,
|
||||
30A3001426DA6692002A734E /* KeychainAccess in Frameworks */,
|
||||
9A996C5726DDF65900A4485D /* Base32 in Frameworks */,
|
||||
9A17C06726DDAAE400C23FAB /* OneTimePassword in Frameworks */,
|
||||
9A1D1CE526E5D1CE0052028E /* OneTimePassword in Frameworks */,
|
||||
30A3001626DA6697002A734E /* SwiftyUserDefaults in Frameworks */,
|
||||
3032DA5626DAF4E500A7728C /* ObjectivePGP in Frameworks */,
|
||||
);
|
||||
|
|
@ -521,10 +521,10 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
30A3001E26DA91C4002A734E /* OneTimePassword in Frameworks */,
|
||||
A26075811EEC6F34005DB03E /* passKit.framework in Frameworks */,
|
||||
30A3002026DA91D7002A734E /* Base32 in Frameworks */,
|
||||
30A3001C26DA91BF002A734E /* SwiftyUserDefaults in Frameworks */,
|
||||
9A1D1CE726E5D2230052028E /* OneTimePassword in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -549,7 +549,7 @@
|
|||
files = (
|
||||
3010CB6026DA4F87008964D2 /* SwiftyUserDefaults in Frameworks */,
|
||||
3010CB6326DA4FE9008964D2 /* FavIcon in Frameworks */,
|
||||
9A996C5526DDF62300A4485D /* OneTimePassword in Frameworks */,
|
||||
9A1F47FA26E5CF4B000C0E01 /* OneTimePassword in Frameworks */,
|
||||
9A996C5326DDF61F00A4485D /* Base32 in Frameworks */,
|
||||
3032DA5426DAF4C200A7728C /* ObjectivePGP in Frameworks */,
|
||||
3010CB6626DA500F008964D2 /* KeychainAccess in Frameworks */,
|
||||
|
|
@ -1087,8 +1087,8 @@
|
|||
30A3001326DA6692002A734E /* KeychainAccess */,
|
||||
30A3001526DA6697002A734E /* SwiftyUserDefaults */,
|
||||
3032DA5526DAF4E500A7728C /* ObjectivePGP */,
|
||||
9A17C06626DDAAE400C23FAB /* OneTimePassword */,
|
||||
9A996C5626DDF65900A4485D /* Base32 */,
|
||||
9A1D1CE426E5D1CE0052028E /* OneTimePassword */,
|
||||
);
|
||||
productName = passKit;
|
||||
productReference = A26075781EEC6F34005DB03E /* passKit.framework */;
|
||||
|
|
@ -1111,8 +1111,8 @@
|
|||
name = passKitTests;
|
||||
packageProductDependencies = (
|
||||
30A3001B26DA91BF002A734E /* SwiftyUserDefaults */,
|
||||
30A3001D26DA91C4002A734E /* OneTimePassword */,
|
||||
30A3001F26DA91D7002A734E /* Base32 */,
|
||||
9A1D1CE626E5D2230052028E /* OneTimePassword */,
|
||||
);
|
||||
productName = passKitTests;
|
||||
productReference = A26075801EEC6F34005DB03E /* passKitTests.xctest */;
|
||||
|
|
@ -1185,7 +1185,7 @@
|
|||
3010CB6526DA500F008964D2 /* KeychainAccess */,
|
||||
3032DA5326DAF4C200A7728C /* ObjectivePGP */,
|
||||
9A996C5226DDF61F00A4485D /* Base32 */,
|
||||
9A996C5426DDF62300A4485D /* OneTimePassword */,
|
||||
9A1F47F926E5CF4B000C0E01 /* OneTimePassword */,
|
||||
);
|
||||
productName = pass;
|
||||
productReference = DC917BD31E2E8231000FDF54 /* Pass.app */;
|
||||
|
|
@ -1285,9 +1285,9 @@
|
|||
3010CB5E26DA4F87008964D2 /* XCRemoteSwiftPackageReference "SwiftyUserDefaults" */,
|
||||
3010CB6126DA4FE9008964D2 /* XCRemoteSwiftPackageReference "FavIcon" */,
|
||||
3010CB6426DA500F008964D2 /* XCRemoteSwiftPackageReference "KeychainAccess" */,
|
||||
3010CB6726DA50B3008964D2 /* XCRemoteSwiftPackageReference "OneTimePassword" */,
|
||||
30A3000C26DA62F4002A734E /* XCRemoteSwiftPackageReference "Base32" */,
|
||||
3032DA5226DAF4C200A7728C /* XCRemoteSwiftPackageReference "ObjectivePGP" */,
|
||||
9A1F47F826E5CF4B000C0E01 /* XCRemoteSwiftPackageReference "OneTimePassword" */,
|
||||
);
|
||||
productRefGroup = DC917BD41E2E8231000FDF54 /* Products */;
|
||||
projectDirPath = "";
|
||||
|
|
@ -2789,14 +2789,6 @@
|
|||
minimumVersion = 4.2.2;
|
||||
};
|
||||
};
|
||||
3010CB6726DA50B3008964D2 /* XCRemoteSwiftPackageReference "OneTimePassword" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mattrubin/OneTimePassword";
|
||||
requirement = {
|
||||
branch = develop;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
3032DA5226DAF4C200A7728C /* XCRemoteSwiftPackageReference "ObjectivePGP" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/krzyzanowskim/ObjectivePGP";
|
||||
|
|
@ -2813,6 +2805,14 @@
|
|||
kind = branch;
|
||||
};
|
||||
};
|
||||
9A1F47F826E5CF4B000C0E01 /* XCRemoteSwiftPackageReference "OneTimePassword" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mssun/OneTimePassword";
|
||||
requirement = {
|
||||
branch = passforios;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
|
|
@ -2866,19 +2866,24 @@
|
|||
package = 3010CB5E26DA4F87008964D2 /* XCRemoteSwiftPackageReference "SwiftyUserDefaults" */;
|
||||
productName = SwiftyUserDefaults;
|
||||
};
|
||||
30A3001D26DA91C4002A734E /* OneTimePassword */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 3010CB6726DA50B3008964D2 /* XCRemoteSwiftPackageReference "OneTimePassword" */;
|
||||
productName = OneTimePassword;
|
||||
};
|
||||
30A3001F26DA91D7002A734E /* Base32 */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 30A3000C26DA62F4002A734E /* XCRemoteSwiftPackageReference "Base32" */;
|
||||
productName = Base32;
|
||||
};
|
||||
9A17C06626DDAAE400C23FAB /* OneTimePassword */ = {
|
||||
9A1D1CE426E5D1CE0052028E /* OneTimePassword */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 3010CB6726DA50B3008964D2 /* XCRemoteSwiftPackageReference "OneTimePassword" */;
|
||||
package = 9A1F47F826E5CF4B000C0E01 /* XCRemoteSwiftPackageReference "OneTimePassword" */;
|
||||
productName = OneTimePassword;
|
||||
};
|
||||
9A1D1CE626E5D2230052028E /* OneTimePassword */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9A1F47F826E5CF4B000C0E01 /* XCRemoteSwiftPackageReference "OneTimePassword" */;
|
||||
productName = OneTimePassword;
|
||||
};
|
||||
9A1F47F926E5CF4B000C0E01 /* OneTimePassword */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9A1F47F826E5CF4B000C0E01 /* XCRemoteSwiftPackageReference "OneTimePassword" */;
|
||||
productName = OneTimePassword;
|
||||
};
|
||||
9A996C5226DDF61F00A4485D /* Base32 */ = {
|
||||
|
|
@ -2886,11 +2891,6 @@
|
|||
package = 30A3000C26DA62F4002A734E /* XCRemoteSwiftPackageReference "Base32" */;
|
||||
productName = Base32;
|
||||
};
|
||||
9A996C5426DDF62300A4485D /* OneTimePassword */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 3010CB6726DA50B3008964D2 /* XCRemoteSwiftPackageReference "OneTimePassword" */;
|
||||
productName = OneTimePassword;
|
||||
};
|
||||
9A996C5626DDF65900A4485D /* Base32 */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 30A3000C26DA62F4002A734E /* XCRemoteSwiftPackageReference "Base32" */;
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@
|
|||
},
|
||||
{
|
||||
"package": "OneTimePassword",
|
||||
"repositoryURL": "https://github.com/mattrubin/OneTimePassword",
|
||||
"repositoryURL": "https://github.com/mssun/OneTimePassword",
|
||||
"state": {
|
||||
"branch": "develop",
|
||||
"revision": "bd2a8fa24057916e4e543ae323e34f75ae744db8",
|
||||
"branch": "passforios",
|
||||
"revision": "cad8872ed9f506bfba6f2ad51673f267602f0879",
|
||||
"version": null
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ public class Password {
|
|||
.usingDigits(getAdditionValue(withKey: Constants.OTP_DIGITS))
|
||||
.usingPeriod(getAdditionValue(withKey: Constants.OTP_PERIOD))
|
||||
.usingCounter(getAdditionValue(withKey: Constants.OTP_COUNTER))
|
||||
.usingRepresentation(getAdditionValue(withKey: Constants.OTP_REPRESENTATION))
|
||||
.build()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
// Copyright © 2018 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import OneTimePassword
|
||||
|
||||
public enum Constants {
|
||||
static let OTP_SECRET = "otp_secret"
|
||||
static let OTP_TYPE = "otp_type"
|
||||
|
|
@ -13,6 +15,7 @@ public enum Constants {
|
|||
static let OTP_PERIOD = "otp_period"
|
||||
static let OTP_DIGITS = "otp_digits"
|
||||
static let OTP_COUNTER = "otp_counter"
|
||||
static let OTP_REPRESENTATION = "otp_representation"
|
||||
static let OTPAUTH = "otpauth"
|
||||
|
||||
public static let OTP_KEYWORDS = [
|
||||
|
|
@ -22,6 +25,7 @@ public enum Constants {
|
|||
OTP_PERIOD,
|
||||
OTP_DIGITS,
|
||||
OTP_COUNTER,
|
||||
OTP_REPRESENTATION,
|
||||
OTPAUTH,
|
||||
]
|
||||
|
||||
|
|
@ -32,6 +36,7 @@ public enum Constants {
|
|||
static let DEFAULT_DIGITS = 6
|
||||
static let DEFAULT_PERIOD = 30.0
|
||||
static let DEFAULT_COUNTER: UInt64? = nil
|
||||
static let DEFAULT_REPRESENTATION: OneTimePassword.Generator.Representation = .numeric
|
||||
|
||||
static let BLANK = " "
|
||||
static let MULTILINE_WITH_LINE_BREAK_INDICATOR = "|"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class TokenBuilder {
|
|||
private var digits: Int? = Constants.DEFAULT_DIGITS
|
||||
private var period: Double? = Constants.DEFAULT_PERIOD
|
||||
private var counter: UInt64? = Constants.DEFAULT_COUNTER
|
||||
private var representation: OneTimePassword.Generator.Representation = Constants.DEFAULT_REPRESENTATION
|
||||
|
||||
func usingName(_ name: String) -> TokenBuilder {
|
||||
self.name = name
|
||||
|
|
@ -79,6 +80,18 @@ class TokenBuilder {
|
|||
return self
|
||||
}
|
||||
|
||||
func usingRepresentation(_ representation: String?) -> TokenBuilder {
|
||||
switch representation {
|
||||
case "numeric":
|
||||
self.representation = .numeric
|
||||
case "steamguard":
|
||||
self.representation = .steamguard
|
||||
default:
|
||||
self.representation = .numeric
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
func build() -> Token? {
|
||||
guard secret != nil, digits != nil else {
|
||||
return nil
|
||||
|
|
@ -95,7 +108,7 @@ class TokenBuilder {
|
|||
}
|
||||
|
||||
private func createToken(factor: Generator.Factor) -> Token? {
|
||||
guard let generator = Generator(factor: factor, secret: secret!, algorithm: algorithm, digits: digits!) else {
|
||||
guard let generator = Generator(factor: factor, secret: secret!, algorithm: algorithm, digits: digits!, representation: representation) else {
|
||||
return nil
|
||||
}
|
||||
return Token(name: name, issuer: "", generator: generator)
|
||||
|
|
|
|||
|
|
@ -317,4 +317,14 @@ class PasswordTest: XCTestCase {
|
|||
XCTAssertNotNil(otpStrings)
|
||||
XCTAssertEqual(otpStrings!.description, "HmacBased".localize())
|
||||
}
|
||||
|
||||
func testSteamOtpStringsToken() {
|
||||
let password = getPasswordObjectWith(content: STEAM_TOTP_URL)
|
||||
let otpStrings = password.getOtpStrings()
|
||||
let otpDescription = otpStrings!.description
|
||||
|
||||
XCTAssertNotNil(otpStrings)
|
||||
XCTAssert(otpDescription.hasPrefix("TimeBased".localize() + " ("))
|
||||
XCTAssert(otpDescription.hasSuffix(")"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,6 +171,27 @@ class TokenBuilderTest: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testRepresentation() {
|
||||
[
|
||||
(nil, .numeric),
|
||||
("steamguard", .steamguard),
|
||||
("numeric", .numeric),
|
||||
("wrong representation", .numeric),
|
||||
].forEach { (inputRepresentation: String?, represenetation: OneTimePassword.Generator.Representation) in
|
||||
var builder = TokenBuilder()
|
||||
.usingSecret(SECRET)
|
||||
.usingType("totp")
|
||||
.usingRepresentation(inputRepresentation)
|
||||
if represenetation == .steamguard {
|
||||
builder = builder
|
||||
.usingDigits("5")
|
||||
.usingAlgorithm("sha1")
|
||||
}
|
||||
let token = builder.build()
|
||||
XCTAssertEqual(token?.generator.representation, represenetation)
|
||||
}
|
||||
}
|
||||
|
||||
func testUnparsableCounter() {
|
||||
let token = TokenBuilder()
|
||||
.usingSecret(SECRET)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ let PASSWORD_PATH = "/path/to/password"
|
|||
let PASSWORD_URL = URL(fileURLWithPath: "/path/to/password")
|
||||
let PASSWORD_STRING = "abcd1234"
|
||||
let TOTP_URL = "otpauth://totp/email@email.com?secret=abcd1234"
|
||||
let STEAM_TOTP_URL = "otpauth://totp/username?secret=12345678901234567890&issuer=Steam&algorithm=SHA1&digits=5&period=30&representation=steamguard"
|
||||
let HOTP_URL = "otpauth://hotp/email@email.com?secret=abcd1234"
|
||||
|
||||
let FIELD = "key" => "value"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue