Skip to content

Commit e1b5767

Browse files
committed
Add SignedArchive project
1 parent 22230e3 commit e1b5767

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3447
-0
lines changed

SignedArchive/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SignedArchive.xcodeproj/xcuserdata

SignedArchive/SignedArchive.xcodeproj/project.pbxproj

+726
Large diffs are not rendered by default.

SignedArchive/SignedArchive.xcodeproj/project.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1000"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "53F5894F21C9B527004A372B"
18+
BuildableName = "extract"
19+
BlueprintName = "extract"
20+
ReferencedContainer = "container:SignedArchive.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
</Testables>
32+
<MacroExpansion>
33+
<BuildableReference
34+
BuildableIdentifier = "primary"
35+
BlueprintIdentifier = "53F5894F21C9B527004A372B"
36+
BuildableName = "extract"
37+
BlueprintName = "extract"
38+
ReferencedContainer = "container:SignedArchive.xcodeproj">
39+
</BuildableReference>
40+
</MacroExpansion>
41+
<AdditionalOptions>
42+
</AdditionalOptions>
43+
</TestAction>
44+
<LaunchAction
45+
buildConfiguration = "Debug"
46+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
47+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
48+
launchStyle = "0"
49+
useCustomWorkingDirectory = "NO"
50+
ignoresPersistentStateOnLaunch = "NO"
51+
debugDocumentVersioning = "YES"
52+
debugServiceExtension = "internal"
53+
allowLocationSimulation = "YES">
54+
<BuildableProductRunnable
55+
runnableDebuggingMode = "0">
56+
<BuildableReference
57+
BuildableIdentifier = "primary"
58+
BlueprintIdentifier = "53F5894F21C9B527004A372B"
59+
BuildableName = "extract"
60+
BlueprintName = "extract"
61+
ReferencedContainer = "container:SignedArchive.xcodeproj">
62+
</BuildableReference>
63+
</BuildableProductRunnable>
64+
<CommandLineArguments>
65+
<CommandLineArgument
66+
argument = "/tmp/passwd.sigzip /tmp/passwd.txt"
67+
isEnabled = "YES">
68+
</CommandLineArgument>
69+
</CommandLineArguments>
70+
<AdditionalOptions>
71+
</AdditionalOptions>
72+
</LaunchAction>
73+
<ProfileAction
74+
buildConfiguration = "Release"
75+
shouldUseLaunchSchemeArgsEnv = "YES"
76+
savedToolIdentifier = ""
77+
useCustomWorkingDirectory = "NO"
78+
debugDocumentVersioning = "YES">
79+
<BuildableProductRunnable
80+
runnableDebuggingMode = "0">
81+
<BuildableReference
82+
BuildableIdentifier = "primary"
83+
BlueprintIdentifier = "53F5894F21C9B527004A372B"
84+
BuildableName = "extract"
85+
BlueprintName = "extract"
86+
ReferencedContainer = "container:SignedArchive.xcodeproj">
87+
</BuildableReference>
88+
</BuildableProductRunnable>
89+
</ProfileAction>
90+
<AnalyzeAction
91+
buildConfiguration = "Debug">
92+
</AnalyzeAction>
93+
<ArchiveAction
94+
buildConfiguration = "Release"
95+
revealArchiveInOrganizer = "YES">
96+
</ArchiveAction>
97+
</Scheme>
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>$(DEVELOPMENT_LANGUAGE)</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>$(PRODUCT_NAME)</string>
15+
<key>CFBundlePackageType</key>
16+
<string>FMWK</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
19+
<key>CFBundleVersion</key>
20+
<string>$(CURRENT_PROJECT_VERSION)</string>
21+
<key>NSHumanReadableCopyright</key>
22+
<string>Copyright © 2018 George Nachman. All rights reserved.</string>
23+
</dict>
24+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// SIGArchiveBuilder.h
3+
// SignedArchive
4+
//
5+
// Created by George Nachman on 12/16/18.
6+
// Copyright © 2018 George Nachman. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
#import "SIGArchiveChunk.h"
12+
13+
NS_ASSUME_NONNULL_BEGIN
14+
15+
@class SIGIdentity;
16+
17+
@interface SIGArchiveBuilder : NSObject
18+
19+
@property (nonatomic, readonly) NSURL *payloadFileURL;
20+
@property (nonatomic, readonly) SIGIdentity *identity;
21+
22+
- (instancetype)initWithPayloadFileURL:(NSURL *)payloadFileURL
23+
identity:(SIGIdentity *)identity NS_DESIGNATED_INITIALIZER;
24+
25+
- (instancetype)init NS_UNAVAILABLE;
26+
27+
- (BOOL)writeToURL:(NSURL *)url
28+
error:(out NSError **)error;
29+
30+
@end
31+
32+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
//
2+
// SIGArchiveBuilder.m
3+
// SignedArchive
4+
//
5+
// Created by George Nachman on 12/16/18.
6+
// Copyright © 2018 George Nachman. All rights reserved.
7+
//
8+
9+
#import "SIGArchiveBuilder.h"
10+
11+
#import "SIGArchiveChunk.h"
12+
#import "SIGArchiveVerifier.h"
13+
#import "SIGCertificate.h"
14+
#import "SIGError.h"
15+
#import "SIGIdentity.h"
16+
#import "SIGKey.h"
17+
#import "SIGSHA2SigningAlgorithm.h"
18+
19+
@implementation SIGArchiveBuilder {
20+
long long _offset;
21+
}
22+
23+
- (instancetype)initWithPayloadFileURL:(NSURL *)url
24+
identity:(SIGIdentity *)identity {
25+
self = [super init];
26+
if (self) {
27+
_payloadFileURL = url;
28+
_identity = identity;
29+
}
30+
return self;
31+
}
32+
33+
#pragma mark - API
34+
35+
- (BOOL)writeToURL:(NSURL *)url
36+
error:(out NSError * _Nullable __autoreleasing *)error {
37+
NSData *signature = [self signature:error];
38+
if (!signature) {
39+
return NO;
40+
}
41+
42+
NSData *certificate = _identity.signingCertificate.data;
43+
if (!certificate) {
44+
if (error) {
45+
*error = [SIGError errorWithCode:SIGErrorCodeNoCertificate];
46+
}
47+
return NO;
48+
}
49+
50+
NSOutputStream *writeStream = [NSOutputStream outputStreamWithURL:url append:NO];
51+
if (!writeStream) {
52+
if (error) {
53+
*error = [SIGError errorWithCode:SIGErrorCodeIOWrite detail:@"Could not create write stream"];
54+
}
55+
return NO;
56+
}
57+
[writeStream open];
58+
59+
if (![self writeHeaderToStream:writeStream error:error]) {
60+
return NO;
61+
}
62+
if (![self writeMetadataToStream:writeStream error:error]) {
63+
return NO;
64+
}
65+
if (![self writePayloadToStream:writeStream error:error]) {
66+
return NO;
67+
}
68+
if (![self writeSignature:signature toStream:writeStream error:error]) {
69+
return NO;
70+
}
71+
if (![self writeCertificate:certificate toStream:writeStream error:error]) {
72+
return NO;
73+
}
74+
[writeStream close];
75+
return YES;
76+
}
77+
78+
#pragma mark - Write Chunks
79+
80+
- (BOOL)writeHeaderToStream:(NSOutputStream *)stream error:(out NSError * _Nullable __autoreleasing *)error {
81+
NSData *data = [SIGArchiveHeaderMagicString dataUsingEncoding:NSUTF8StringEncoding];
82+
const NSInteger desiredLength = data.length;
83+
SIGArchiveChunkWriter *chunkWriter = [[SIGArchiveChunkWriter alloc] initWithTag:SIGArchiveTagHeader
84+
length:desiredLength
85+
offset:_offset];
86+
const BOOL ok = [chunkWriter writeData:data
87+
toStream:stream
88+
error:error];
89+
_offset += chunkWriter.chunkLength;
90+
return ok;
91+
}
92+
93+
- (BOOL)writePayloadToStream:(NSOutputStream *)writeStream error:(out NSError * _Nullable __autoreleasing *)errorOut {
94+
NSInputStream *readStream = [[NSInputStream alloc] initWithURL:_payloadFileURL];
95+
if (!readStream) {
96+
return NO;
97+
}
98+
[readStream open];
99+
100+
NSError *error = nil;
101+
NSInteger length = [[NSFileManager defaultManager] attributesOfItemAtPath:_payloadFileURL.path error:&error].fileSize;
102+
if (length <= 0 || error != nil) {
103+
if (errorOut) {
104+
*errorOut = [SIGError errorWrapping:error
105+
code:SIGErrorCodeIORead
106+
detail:@"Error checking file size"];
107+
}
108+
return NO;
109+
}
110+
SIGArchiveChunkWriter *chunkWriter = [[SIGArchiveChunkWriter alloc] initWithTag:SIGArchiveTagPayload
111+
length:length
112+
offset:_offset];
113+
const BOOL ok = [chunkWriter writeStream:readStream
114+
toStream:writeStream
115+
error:errorOut];
116+
_offset += chunkWriter.chunkLength;
117+
return ok;
118+
}
119+
120+
- (BOOL)writeMetadataToStream:(NSOutputStream *)writeStream error:(out NSError * _Nullable __autoreleasing *)error {
121+
NSArray<NSString *> *fields = @[ @"version=1",
122+
@"digest-type=SHA2" ];
123+
NSString *metadata = [fields componentsJoinedByString:@"\n"];
124+
NSData *data = [metadata dataUsingEncoding:NSUTF8StringEncoding];
125+
SIGArchiveChunkWriter *chunkWriter = [[SIGArchiveChunkWriter alloc] initWithTag:SIGArchiveTagMetadata
126+
length:data.length
127+
offset:_offset];
128+
const BOOL ok = [chunkWriter writeData:data
129+
toStream:writeStream
130+
error:error];
131+
_offset += chunkWriter.chunkLength;
132+
return ok;
133+
}
134+
135+
- (BOOL)writeSignature:(NSData *)signature toStream:(NSOutputStream *)writeStream error:(out NSError * _Nullable __autoreleasing *)error {
136+
SIGArchiveChunkWriter *chunkWriter = [[SIGArchiveChunkWriter alloc] initWithTag:SIGArchiveTagSignature
137+
length:signature.length
138+
offset:_offset];
139+
const BOOL ok = [chunkWriter writeData:signature
140+
toStream:writeStream
141+
error:error];
142+
_offset += chunkWriter.chunkLength;
143+
return ok;
144+
}
145+
146+
- (BOOL)writeCertificate:(NSData *)certificate toStream:(NSOutputStream *)writeStream error:(out NSError * _Nullable __autoreleasing *)error {
147+
SIGArchiveChunkWriter *chunkWriter = [[SIGArchiveChunkWriter alloc] initWithTag:SIGArchiveTagCertificate
148+
length:certificate.length
149+
offset:_offset];
150+
const BOOL ok = [chunkWriter writeData:certificate
151+
toStream:writeStream
152+
error:error];
153+
_offset += chunkWriter.chunkLength;
154+
return ok;
155+
}
156+
157+
#pragma mark - Signing
158+
159+
- (id<SIGSigningAlgorithm>)signingAlgorithm:(out NSError **)error {
160+
id<SIGSigningAlgorithm> algorithm = [[SIGSHA2SigningAlgorithm alloc] init];
161+
if (!algorithm) {
162+
if (error) {
163+
*error = [SIGError errorWithCode:SIGErrorCodeAlgorithmCreationFailed];
164+
}
165+
}
166+
return algorithm;
167+
}
168+
169+
- (NSData *)signature:(out NSError **)error {
170+
id<SIGSigningAlgorithm> algorithm = [self signingAlgorithm:error];
171+
if (!algorithm) {
172+
return nil;
173+
}
174+
175+
NSInputStream *readStream = [NSInputStream inputStreamWithFileAtPath:_payloadFileURL.path];
176+
if (!readStream) {
177+
if (error) {
178+
*error = [SIGError errorWithCode:SIGErrorCodeIORead];
179+
}
180+
return nil;
181+
}
182+
183+
return [algorithm signatureForInputStream:readStream
184+
usingIdentity:_identity
185+
error:error];
186+
}
187+
188+
@end

0 commit comments

Comments
 (0)