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 support to read multiple public keys from a PEM file #22

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ Carthage
Carthage/Checkouts

Carthage/Build

.DS_Store
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ SwiftyRSA Changelog

# master
- Add support for SHA2 (224,256,384 & 512 bits) digest algorithms
- `verifySHA1SignatureData` & `signSHA1Digest` are now deprecated; use `verifySignature()`
- `verifySHA1SignatureData` & `signSHA1Digest` are now deprecated; use `verifySignature()`
and `signDigest()`
- Objective-C sign & verification functions now require a `digestMethod:` parameter
- Added support to read multiple keys from an input file using `publicKeysFromString()`.
[#22](https://github.com/TakeScoop/SwiftyRSA/pull/22)

# [0.3.0]

Expand Down
6 changes: 6 additions & 0 deletions SwiftyRSA.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
934AB81C1D36E45B00365679 /* multiple-keys-testcase.pem in Resources */ = {isa = PBXBuildFile; fileRef = 934AB81A1D36BA8D00365679 /* multiple-keys-testcase.pem */; };
BB8460AE1CC608F6006F802C /* NSData+SHA.h in Headers */ = {isa = PBXBuildFile; fileRef = BB8460AC1CC608F6006F802C /* NSData+SHA.h */; settings = {ATTRIBUTES = (Public, ); }; };
BB8460AF1CC608F6006F802C /* NSData+SHA.m in Sources */ = {isa = PBXBuildFile; fileRef = BB8460AD1CC608F6006F802C /* NSData+SHA.m */; };
C01F96141C5AC3E300F232AC /* SwiftyRSAObjcTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C01F96131C5AC3E300F232AC /* SwiftyRSAObjcTests.m */; };
Expand All @@ -33,6 +34,8 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
934AB81A1D36BA8D00365679 /* multiple-keys-testcase.pem */ = {isa = PBXFileReference; lastKnownFileType = text; path = "multiple-keys-testcase.pem"; sourceTree = "<group>"; };
934AB81B1D36BAC700365679 /* multiple-keys-testcase.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "multiple-keys-testcase.sh"; sourceTree = "<group>"; };
BB8460AC1CC608F6006F802C /* NSData+SHA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+SHA.h"; sourceTree = "<group>"; };
BB8460AD1CC608F6006F802C /* NSData+SHA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+SHA.m"; sourceTree = "<group>"; };
C01F96131C5AC3E300F232AC /* SwiftyRSAObjcTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SwiftyRSAObjcTests.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -136,6 +139,8 @@
C03D82961B45E886008711CF /* swiftyrsa-private.pem */,
C03D82971B45E886008711CF /* swiftyrsa-public.der */,
C03D82981B45E886008711CF /* swiftyrsa-public.pem */,
934AB81A1D36BA8D00365679 /* multiple-keys-testcase.pem */,
934AB81B1D36BAC700365679 /* multiple-keys-testcase.sh */,
);
path = keys;
sourceTree = "<group>";
Expand Down Expand Up @@ -244,6 +249,7 @@
C0646A481CAF29E000587FF1 /* swiftyrsa-private-headerless.pem in Resources */,
C03D829A1B45E886008711CF /* swiftyrsa-public.der in Resources */,
C0646A491CAF29E000587FF1 /* swiftyrsa-public-headerless.pem in Resources */,
934AB81C1D36E45B00365679 /* multiple-keys-testcase.pem in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
skipped = "NO">
Expand Down
58 changes: 57 additions & 1 deletion SwiftyRSA/SwiftyRSA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public class SwiftyRSA: NSObject {
}

/**
Sign a `String` using a private key. The supplied string will be hashed using the specified
Sign a `String` using a private key. The supplied string will be hashed using the specified
hashing function and the resulting digest will be signed.

- parameter str: The `String` to be signed.
Expand Down Expand Up @@ -220,6 +220,62 @@ public class SwiftyRSA: NSObject {
return try addKey(data, isPublic: false)
}

/** The regular expression used to find public key armor */
let publicKeyRegexp : NSRegularExpression? = {
let publicKeyRegexp = "(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)"

return try? NSRegularExpression(pattern: publicKeyRegexp, options: .DotMatchesLineSeparators)
}()

/**
Takes an input string, scans for public key sections, and then returns `SecKeyRef`s for any valid keys found

- This method scans the file for public key armor - if no keys are found, an empty array is returned
- Each public key block found is "parsed" by `publicKeyFromPEMString()` - should that method throw, the error is _swallowed_ and not rethrown

This becomes helpful when reading multiple keys in from a single file, or when you have

- parameter inputPEMString: The string to use to parse out values
- returns: An array of `SecKeyRef` objects

- note: This method is marked as `@nonobjc` because NSArray doesn't support storing `SecKeyRef` using generics. If it can be easily exposed to ObjC as is, this can be changed - but currently, cannot be done without wrapping `SecKeyRef`'s which seems circuitous (as this is a fairly Swift'y library).
*/
@nonobjc public func publicKeysFromString(inputPEMString:String) -> [SecKeyRef] {
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason for making this unavailable from objc?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

[SecKeyRef] cannot be translated to Objective-C because NSArray doesn't support NSArray<SecKeyRef> - the @nonobjc is there to be sure that anyone reading the code sees that. I'll add a note as to why.

I added it because when I went to test this from ObjC I couldn't see the method, and couldn't figure out why for a while.

var response = [SecKeyRef]()

// If our regexp isn't valid, or the input string is empty, we can't move forward…
guard let publicKeyRegexp = publicKeyRegexp where inputPEMString.characters.count > 0 else {
return response
}

let all = NSRange(
location: 0,
length: inputPEMString.characters.count
)

let matches = publicKeyRegexp.matchesInString(
inputPEMString,
options: NSMatchingOptions(rawValue: 0),
range: all
)

for result in matches {
let match = result.rangeAtIndex(1)
let start = inputPEMString.startIndex.advancedBy(match.location)
let end = start.advancedBy(match.length)

let range = Range<String.Index>(start..<end)

let thisKey = inputPEMString[range]

if let key = try? self.publicKeyFromPEMString(thisKey) {
response.append(key)
}
}

return response
}

// Encrypts data with a RSA key
public func encryptData(data: NSData, publicKey: SecKeyRef, padding: SecPadding) throws -> NSData {
let blockSize = SecKeyGetBlockSize(publicKey)
Expand Down
Binary file removed SwiftyRSATests/.DS_Store
Binary file not shown.
25 changes: 25 additions & 0 deletions SwiftyRSATests/SwiftyRSATests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,29 @@ class SwiftyRSATests: XCTestCase {

}

/// See also: multiple-keys-testcase.sh for the generation of this file
func testReadingPublicKeysFromComplexPEMFileWorksCorrectly(){
Copy link
Contributor

Choose a reason for hiding this comment

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

Lots of spaces in those test methods. Can you compact all these?

let input = TestUtils.pemKeyString(name: "multiple-keys-testcase")

XCTAssertEqual(
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be a one liner.

SwiftyRSA().publicKeysFromString(input).count,
9
)
}

func testReadingPublicKeysFromEmptyPEMFileReturnsEmptyArray(){
XCTAssertEqual(
SwiftyRSA().publicKeysFromString("").count,
0
)
}

func testReadingPublicKeysFromPrivateKeyPEMFileReturnsEmptyArray(){
let input = TestUtils.pemKeyString(name: "swiftyrsa-private")

XCTAssertEqual(
SwiftyRSA().publicKeysFromString(input).count,
0
)
}
}
100 changes: 100 additions & 0 deletions SwiftyRSATests/Wildfire.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// Wildfire.swift
// SwiftyRSA
//
// Created by Mark Hughes on 7/15/16.
// Copyright © 2016 Scoop. All rights reserved.
//

import XCTest
import SwiftyRSA
import Security

public protocol SwiftyRSABackendProtocol {
func generateHash(input: String, hashType: DigestType) -> String;
}

public class SecTransformBackend : NSObject, SwiftyRSABackendProtocol {
public func generateHash(input: String, hashType: DigestType) -> String {
// Total sham mock

let response = "";

return response;
}
}

public class MockBackend : NSObject, SwiftyRSABackendProtocol {
public func generateHash(input: String, hashType: DigestType) -> String {
return "";
}
}

protocol ConcreteBackendTests {
func testSHA256Reference();
}

class ComposableTester {

}

class SecTransformBackendTest : XCTestCase, ConcreteBackendTests {
func getInstance(){
return SecTransformBackend()
}

func testSHA256Reference() {
XCTAssert(

)
}
}
























class Wildfire: XCTestCase {

override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}

func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}

func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}

}
Loading