Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added obfuscation for keys #67

Merged
merged 7 commits into from
Jul 24, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ UtiliKit
This library provides several useful and often common additions for iOS applications. These extensions, protocols, and structs are designed to simplify boilerplate code as well as remove common "Stringly-typed" use cases.

### Key Concepts
This library is divided into 5 parts.
This library is divided into 6 parts.
* Instantiation - This subspec changes "Stringly-typed" view instantiation, view controller instantiation, and reusable view dequeuing into type-safe function calls.
* General - This subspec includes extensions for both FileManager and UIView. These simplify getting common URLs and programmatically adding views down to simple variables and function calls.
* Version - This subspec simplifies the display of version and build numbers.
* TimelessDate - This subspec is an abstraction away from Date and Calendar. It is primarily designed to be used for simple scheduling and day comparisons in which the time is less important that the actual day.
* Container - This subspec provides a simple ContainerViewController without any built-in navigation construct.
* Obfuscation - This subspec provides simple routines to remove plaintext passwords or keys from your source code.

### Usage
#### Reusable Views
Expand Down Expand Up @@ -226,6 +227,14 @@ When initializing `ActiveLabel` in Storyboards or Xibs you must set the labels t

When using `ActiveLabel` for snapshot tests you can center the gradient by calling `configureForSnapshotTest()` on your label.

#### ObfuscatedKey

To use an obfuscated key in your code, create one and use the builder variables to encode your key.

``` swift
let key = ObfuscatedKey().T.h.i.s.underscore.I.s.dash.o.b.f.u.s.c.a.t.e.d.value
```

### Example

To run the example project, clone the repo, and run `pod install` from the Example directory first.
Expand Down
6 changes: 6 additions & 0 deletions Sources/UtiliKit/ActiveLabel/ActiveLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import UIKit
/// - Note: `ActiveLabel` loading indicators do not scale with Dynamic Type at this time. The text in the label does scale as expected.
@IBDesignable
class ActiveLabel: UILabel {

// codebeat:disable[TOO_MANY_FUNCTIONS]

static let loadingGray: UIColor = UIColor(red: 233.0/255.0, green: 231.0/255.0, blue: 237.0/255.0, alpha: 1.0)

/// Struct used to represent how an `ActiveLabel` should be displayed. Should be passed into the `ActiveLabel` convenience initializer.
Expand Down Expand Up @@ -382,4 +385,7 @@ private extension ActiveLabel {

return animation
}

// codebeat:enable[TOO_MANY_FUNCTIONS]

}
109 changes: 109 additions & 0 deletions Sources/UtiliKit/Obfuscation/ObfuscatedKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//
// ObfuscatedKey.swift
// UtiliKit-iOS
//
// Created by Russell Mirabelli on 7/23/19.
// Copyright © 2019 CocoaPods. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we need to update the copyright here to "Bottle Rocket Studios". Could you go ahead and update this comment and make the change in the project file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

//

// Inspired by https://github.com/onmyway133/Arcane/blob/master/Sources/Arcane/Obfuscator.swift

import Foundation

/// One should never commit keys directly into one's source; this is an unsafe practice.
/// When it is impossible to avoid doing so, the key should at least be obfuscated.
/// By using the ObfuscatedKey struct, you can build a human-readable key that nonetheless
/// will not appear simply by running "strings" against your compiled code, and will even
/// not appear as a string within your source code.
struct ObfuscatedKey {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to be public.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

private let _value: String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we lose the internal variable and use public private(set) value: String ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not available on a "let"; I believe that the immutability of a "let" is important to make the general builder technique make sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point - withdrawn.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't help but feel like I'm missing something here - what does the private let _value: String and public var value { return _value } get us here over a single immutable public let value. As far as I can tell, we aren't mutating it or validating internally and the same-file extensions should have the same access regardless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. Since my merge is still blocked by the license (ugh), I'll think about this and see if there is a good reason I can find.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed, changed.


init() {
self._value = ""
}

init(_ value: String) {
self._value = value
}

var value: String {
get {
return _value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use the implicit getter here instead of manually specifying the get block.

var value: String {
    return _value
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
}

// codebeat:disable[TOO_MANY_FUNCTIONS]
var A: ObfuscatedKey { return ObfuscatedKey(_value + "A") }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to throw these into a public extension to alleviate the need to define each of these as public var ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice way to avoid all the publics. Done, and thanks!

var B: ObfuscatedKey { return ObfuscatedKey(_value + "B") }
var C: ObfuscatedKey { return ObfuscatedKey(_value + "C") }
var D: ObfuscatedKey { return ObfuscatedKey(_value + "D") }
var E: ObfuscatedKey { return ObfuscatedKey(_value + "E") }
var F: ObfuscatedKey { return ObfuscatedKey(_value + "F") }
var G: ObfuscatedKey { return ObfuscatedKey(_value + "G") }
var H: ObfuscatedKey { return ObfuscatedKey(_value + "H") }
var I: ObfuscatedKey { return ObfuscatedKey(_value + "I") }
var J: ObfuscatedKey { return ObfuscatedKey(_value + "J") }
var K: ObfuscatedKey { return ObfuscatedKey(_value + "K") }
var L: ObfuscatedKey { return ObfuscatedKey(_value + "L") }
var M: ObfuscatedKey { return ObfuscatedKey(_value + "M") }
var N: ObfuscatedKey { return ObfuscatedKey(_value + "N") }
var O: ObfuscatedKey { return ObfuscatedKey(_value + "O") }
var P: ObfuscatedKey { return ObfuscatedKey(_value + "P") }
var Q: ObfuscatedKey { return ObfuscatedKey(_value + "Q") }
var R: ObfuscatedKey { return ObfuscatedKey(_value + "R") }
var S: ObfuscatedKey { return ObfuscatedKey(_value + "S") }
var T: ObfuscatedKey { return ObfuscatedKey(_value + "T") }
var U: ObfuscatedKey { return ObfuscatedKey(_value + "U") }
var V: ObfuscatedKey { return ObfuscatedKey(_value + "V") }
var W: ObfuscatedKey { return ObfuscatedKey(_value + "W") }
var X: ObfuscatedKey { return ObfuscatedKey(_value + "X") }
var Y: ObfuscatedKey { return ObfuscatedKey(_value + "Y") }
var Z: ObfuscatedKey { return ObfuscatedKey(_value + "Z") }

var a: ObfuscatedKey { return ObfuscatedKey(_value + "a") }
var b: ObfuscatedKey { return ObfuscatedKey(_value + "b") }
var c: ObfuscatedKey { return ObfuscatedKey(_value + "c") }
var d: ObfuscatedKey { return ObfuscatedKey(_value + "d") }
var e: ObfuscatedKey { return ObfuscatedKey(_value + "e") }
var f: ObfuscatedKey { return ObfuscatedKey(_value + "f") }
var g: ObfuscatedKey { return ObfuscatedKey(_value + "g") }
var h: ObfuscatedKey { return ObfuscatedKey(_value + "h") }
var i: ObfuscatedKey { return ObfuscatedKey(_value + "i") }
var j: ObfuscatedKey { return ObfuscatedKey(_value + "j") }
var k: ObfuscatedKey { return ObfuscatedKey(_value + "k") }
var l: ObfuscatedKey { return ObfuscatedKey(_value + "l") }
var m: ObfuscatedKey { return ObfuscatedKey(_value + "m") }
var n: ObfuscatedKey { return ObfuscatedKey(_value + "n") }
var o: ObfuscatedKey { return ObfuscatedKey(_value + "o") }
var p: ObfuscatedKey { return ObfuscatedKey(_value + "p") }
var q: ObfuscatedKey { return ObfuscatedKey(_value + "q") }
var r: ObfuscatedKey { return ObfuscatedKey(_value + "r") }
var s: ObfuscatedKey { return ObfuscatedKey(_value + "s") }
var t: ObfuscatedKey { return ObfuscatedKey(_value + "t") }
var u: ObfuscatedKey { return ObfuscatedKey(_value + "u") }
var v: ObfuscatedKey { return ObfuscatedKey(_value + "v") }
var w: ObfuscatedKey { return ObfuscatedKey(_value + "w") }
var x: ObfuscatedKey { return ObfuscatedKey(_value + "x") }
var y: ObfuscatedKey { return ObfuscatedKey(_value + "y") }
var z: ObfuscatedKey { return ObfuscatedKey(_value + "z") }

var n0: ObfuscatedKey { return ObfuscatedKey(_value + "0") }
var n1: ObfuscatedKey { return ObfuscatedKey(_value + "1") }
var n2: ObfuscatedKey { return ObfuscatedKey(_value + "2") }
var n3: ObfuscatedKey { return ObfuscatedKey(_value + "3") }
var n4: ObfuscatedKey { return ObfuscatedKey(_value + "4") }
var n5: ObfuscatedKey { return ObfuscatedKey(_value + "5") }
var n6: ObfuscatedKey { return ObfuscatedKey(_value + "6") }
var n7: ObfuscatedKey { return ObfuscatedKey(_value + "7") }
var n8: ObfuscatedKey { return ObfuscatedKey(_value + "8") }
var n9: ObfuscatedKey { return ObfuscatedKey(_value + "9") }

var dot: ObfuscatedKey { return ObfuscatedKey(_value + ".") }
var dash: ObfuscatedKey { return ObfuscatedKey(_value + "-") }
var underscore: ObfuscatedKey { return ObfuscatedKey(_value + "_") }

func anything(_ extra: String) -> ObfuscatedKey {
return ObfuscatedKey(_value + extra)
}
// codebeat:enable[TOO_MANY_FUNCTIONS]
}
5 changes: 4 additions & 1 deletion Sources/UtiliKit/TimelessDate/TimelessDate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ extension Calendar {
public struct TimelessDate: Comparable, Equatable, Hashable {
private(set) var date: Date
private var calendar = Calendar.current


// codebeat:disable[TOO_MANY_FUNCTIONS]

/**
Returns the DateInterval between the TimelessDate and 1 January 2001.

Expand Down Expand Up @@ -194,6 +196,7 @@ public struct TimelessDate: Comparable, Equatable, Hashable {
public static func ==(lhs: TimelessDate, rhs: TimelessDate) -> Bool {
return lhs.dateIntervalSinceReferenceDate == rhs.dateIntervalSinceReferenceDate
}
// codebeat:enable[TOO_MANY_FUNCTIONS]
}

// MARK: CustomStringConvertable
Expand Down
44 changes: 44 additions & 0 deletions Tests/ObfuscationTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// ObfuscationTests.swift
// UtiliKit-iOSTests
//
// Created by Russell Mirabelli on 7/23/19.
// Copyright © 2019 CocoaPods. All rights reserved.
//

import XCTest
@testable import UtiliKit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking a regular import might work just as well here since we're testing public APIs (also, we might need to make much ObfuscatedKey.swift public so that it's usable in client code).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


class ObfuscationTests: XCTestCase {

func testSimpleObfuscatedString() {
let key = ObfuscatedKey().A.B.A.B.value
let expected = "ABAB"
XCTAssert(key == expected, "Keys do not match: \(key) is not \(expected)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor, but you might consider using XCTAssertEqual() instead of the more generic XCTAssert().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

func testUppercase() {
let key = ObfuscatedKey().A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.value
let expected = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
XCTAssert(key == expected, "Keys do not match: \(key) is not \(expected)")
}

func testLowercase() {
let key = ObfuscatedKey().a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.value
let expected = "abcdefghijklmnopqrstuvwxyz"
XCTAssert(key == expected, "Keys do not match: \(key) is not \(expected)")
}

func testDigits() {
let key = ObfuscatedKey().n0.n1.n2.n3.n4.n5.n6.n7.n8.n9.value
let expected = "0123456789"
XCTAssert(key == expected, "Keys do not match: \(key) is not \(expected)")
}

func testExtras() {
let key = ObfuscatedKey().dot.dash.underscore.anything("=").value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor, but we might consider renaming anything(_:) to read a little better here at the call site. Some potential suggestions:

  • appending(_:)
  • explicit(_:)
  • extra(_:)
  • additional(_:)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about literal(_:) ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda like additional. What about calling it add?
add(_:)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used literal.

let expected = ".-_="
XCTAssert(key == expected, "Keys do not match: \(key) is not \(expected)")
}

}
4 changes: 4 additions & 0 deletions UtiliKit.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ s.subspec 'ActiveLabel' do |activeLabel|
activeLabel.source_files = 'Sources/UtiliKit/ActiveLabel/*.swift'
end

s.subspec 'Obfuscation' do |obfuscation|
obfuscation.source_files = 'Sources/UtiliKit/Obfuscation/*.swift'
end

end
16 changes: 16 additions & 0 deletions UtiliKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
5C574BFF22675A51003D1641 /* SnapshotTesting.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5C574BFC22675999003D1641 /* SnapshotTesting.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
62F5256D2257F4F50052B8E7 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 62F5256C2257F4F50052B8E7 /* README.md */; };
62F5256F2257F4FE0052B8E7 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 62F5256E2257F4FE0052B8E7 /* CHANGELOG.md */; };
7D5611B822E79AD40017008D /* ObfuscationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D5611B722E79AD40017008D /* ObfuscationTests.swift */; };
7D5611BA22E79B4C0017008D /* ObfuscatedKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D5611B922E79B4C0017008D /* ObfuscatedKey.swift */; };
8677314220601BB400C54343 /* UtiliKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8677313920601BB400C54343 /* UtiliKit.framework */; };
8677315720601D1A00C54343 /* UtiliKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 869826261FE87BFA0024B73D /* UtiliKitTests.swift */; };
8677315820601D1A00C54343 /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 869826271FE87BFA0024B73D /* DateTests.swift */; };
Expand Down Expand Up @@ -107,6 +109,8 @@
5C574BFC22675999003D1641 /* SnapshotTesting.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SnapshotTesting.framework; path = Carthage/Build/iOS/SnapshotTesting.framework; sourceTree = "<group>"; };
62F5256C2257F4F50052B8E7 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
62F5256E2257F4FE0052B8E7 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
7D5611B722E79AD40017008D /* ObfuscationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObfuscationTests.swift; sourceTree = "<group>"; };
7D5611B922E79B4C0017008D /* ObfuscatedKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObfuscatedKey.swift; sourceTree = "<group>"; };
8677313920601BB400C54343 /* UtiliKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UtiliKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8677314120601BB400C54343 /* UtiliKit-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "UtiliKit-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
8677315A20601DD800C54343 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -237,6 +241,7 @@
isa = PBXGroup;
children = (
869826271FE87BFA0024B73D /* DateTests.swift */,
7D5611B722E79AD40017008D /* ObfuscationTests.swift */,
869826261FE87BFA0024B73D /* UtiliKitTests.swift */,
0ED9476220FD461300B642AB /* ContainerTests.swift */,
5C574BFA2264ED61003D1641 /* ActiveLabelTests.swift */,
Expand All @@ -245,6 +250,14 @@
path = Tests;
sourceTree = "<group>";
};
7D5611B622E79AAE0017008D /* Obfuscation */ = {
isa = PBXGroup;
children = (
7D5611B922E79B4C0017008D /* ObfuscatedKey.swift */,
);
path = Obfuscation;
sourceTree = "<group>";
};
8677315920601DD800C54343 /* Supporting Files */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -278,6 +291,7 @@
8698CFA220619EAD0065AE20 /* Container */,
8698CFA720619EAD0065AE20 /* General */,
8698CFAA20619EAD0065AE20 /* Instantiation */,
7D5611B622E79AAE0017008D /* Obfuscation */,
8698CFB220619EAD0065AE20 /* TimelessDate */,
8698CFB520619EAD0065AE20 /* Version */,
);
Expand Down Expand Up @@ -592,6 +606,7 @@
0EC8025C209CE9C90051F732 /* Configurable.swift in Sources */,
8698CFC820619EAD0065AE20 /* TimelessDate.swift in Sources */,
8698CFC320619EAD0065AE20 /* StoryboardIdentifiable.swift in Sources */,
7D5611BA22E79B4C0017008D /* ObfuscatedKey.swift in Sources */,
8698CFC920619EAD0065AE20 /* Bundle+Extensions.swift in Sources */,
8698CFC520619EAD0065AE20 /* UIStoryboard+Extensions.swift in Sources */,
8698CFC220619EAD0065AE20 /* ReuseIdentifiable.swift in Sources */,
Expand All @@ -615,6 +630,7 @@
0ED9476420FD473700B642AB /* ContainerTests.swift in Sources */,
8677315720601D1A00C54343 /* UtiliKitTests.swift in Sources */,
8677315820601D1A00C54343 /* DateTests.swift in Sources */,
7D5611B822E79AD40017008D /* ObfuscationTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down