Wednesday, December 23, 2015

Command line swift

It is perhaps quixotic (unrealistic or impractical), but I like doing things without Xcode sometimes. Xcode is a complicated beast. So in testing code I've been doing

swift test.swift

from the command line, updated from

xcrun swift test.swift

which I used to do.

I was excited to find that it is possible to use code in more than one Swift file, like this:

swiftc file1.swift main.swift -o prog
./prog


Credit:
http://stackoverflow.com/questions/29089861/how-to-import-modules-without-an-xcode-project-in-swift


Reading the man page for swift and swiftc I find these ideas:

swiftc -emit-library card.swift

which runs and gives libcard.dylib but I have no idea how to import it from Swift.

There is also -emit-module, which gives card.swiftdoc and card.swiftmodule but I have no idea how to use them.

Maybe I should look inside Xcode and try to figure out how it accomplishes what it does?

CommonCrypto5

I came across another introductory article about how to import CommonCrypto from Swift.

Recall what we did before following this post:

Method 1:

- obtain a bridging header by adding a dummy Objective-C file in Xcode
- in the header, do #import <CommonCrypto/CommonCrypto.h>

The library functions will be available from an Xcode Swift Cocoa app project.

Method 2:

Make CommonCrypto quack like a Framework by putting a file module.map with appropriate code, inside the directory that holds OS X SDK frameworks:


/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform\
/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks


With that single change:

- we no longer need the bridging header from an Xcode project
- we can use CommonCrypto in a framework
- we can use it in an Xcode Playground

- we can also do this:


test.swift:
import CommonCrypto
print(CC_SHA1_DIGEST_LENGTH)

> swift test.swift
20
>


The referenced article shows a different way to use CommonCrypto inside a framework (where the bridging header trick won't work).

Put the module.map

module.map:
module CommonCrypto [system] {
header "/usr/include/CommonCrypto/CommonCrypto.h"
export *
}


inside your project directory (not necessary to use Xcode). Following the instructions:

Now add the new module to Import Paths under Swift Compiler – Search Paths in your project settings. Use ${SRCROOT} in the module path (e.g. ${SRCROOT}/CommonCrypto) to insure that the project works no matter where it’s checked out.

Then you can just use import CommonCrypto.

Other notable items:

- use of NSData and NSMutableData types for the buffers
- size_t(key.length) and size_t(data.length), in calling the functions

Tuesday, December 22, 2015

Swift 2 book

I've been reworking my "book" on Swift, to update from Swift 1 to 2 and add some more examples. It is still early days, but after a week of work I am ready to put up a rough draft here.

You can read it right there on github, or you can clone the project and build the html with Sphinx if you have that. Here is a gist of a small part of it:

Wednesday, December 16, 2015

A bit more about pointers in Swift

I looked into the problems with Open SSL under Swift a bit more. To reassure myself that I can still deal with C pointers, I wrote a quick demo. Here is the gist:



We will print an array passed into the function f1, modify that array in place in f2, and change each value to a different data type and write that to a second array in f3.

f3 takes the fourth root. Because the resulting type is a floating point number (I used a double), I need a second array into which the values are written. It works as you'd expect:


> clang -Wall p1.c -o prog
> ./prog
f1
1 2 3 4 5
f2
1 4 9 16 25
f3
1.00 1.41 1.73 2.00 2.24
>


And the point is that the code to use this C "library" from Swift is trivial. To keep path issues away, I simply added this C file to a new Xcode Cocoa app project written in Swift. I get a bridging header in the usual way, and add to it a statement #import "p.h", as well as dragging the header into the project.

p.h:

void f1(int *, int);
void f2(int *, int);
void f3(int *, double *, int);


To actually use the C code, we just do this in a function called from the AppDelegate:



It prints:


Swift: a = [1, 2, 3, 4, 5]
f1
1 2 3 4 5
f2
f1
1 4 9 16 25
Swift: a = [1, 4, 9, 16, 25]
f3
Swift b: 1.000 1.414 1.732 2.000 2.236


And this code never ever crashes. Well, not that I observed, anyway. I got the idea of testing whether it would crash in 100 trials. In a shellscript:


n=1
while [ $n != 100 ]
do
    open -a "MyApp"
    sleep 1
    osascript -e 'quit app "MyApp"'
    n=$((n+1))
done


open we know, but using osascript to kill an app, that's special.

Although this runs, I got to thinking it probably won't report a crash. I should try Python.



It's actually fairly annoying, because each time the app launches, it grabs the focus!


97
98
99
100
>


That's a relief.

Anyway, it's not hard to puzzle out where we need UnsafeMutablePointer<Int32> and where we need UnsafeMutablePointer<Double>.

Of course, we knew this was robust, because CommonCrypto worked so well.

The problem seems to be in Open SSL. I just started learning to use the debugger lldb. But it is clear that the crash that occurs when we have called AES_set_encrypt_key often occurs sometime later, after the enclosing function test returns, or even back in the AppDelegate. We are not messing up the call.

I don't know how to fix that.

Monday, December 14, 2015

Carthage

This morning I was ready to move on to openssl and try to use that in a Swift Cocoa app. I came across this, which talks about Cocoapods.

So what is that? It is a dependency manager for iOS and macosx. If you want to add various libraries to your app, this will help keep the versions straight. Then I became aware that there is another such beast called Carthage. And I immediately liked their philosophy: "ruthlessly simple."

And their background at github.

So I worked through this tutorial, which didn't work in part, but that may be because it's about iOS, and I don't know much about iOS.

Here is the bottom line: we can get Carthage with Homebrew:

brew install carthage

Take a look:

> brew info carthage
carthage: stable 0.11 (bottled), HEAD
Decentralized dependency manager for Cocoa
https://github.com/Carthage/Carthage
/usr/local/Cellar/carthage/0.11 (29 files, 11M) *
Poured from bottle
From: https://github.com/Homebrew/homebrew/blob/master/Library/Formula/carthage.rb
>

Using it is really simple. We make a new Xcode project (UseEncryptor) that will use the Encryptor framework (which is on github here).

(It will also work with SSH).

In the root directory of UseEncryptor

> touch Cartfile
> open -a Xcode Cartfile

Put this text:

github "https://github.com/telliott99/Encryptor" "master"

The "master" part is important. A fundamental use of Carthage is to get compatible versions of all the frameworks/libraries you need. Since I don't have versions, I need something there. It could be a specific commit, like "bf155b9".

> carthage update
*** Fetching Encryptor
*** Checking out Encryptor at "6d1f5025d33657220a77850253f83aacc41e439c"
*** xcodebuild output can be found in /var/folders/1l/d7lmw_ln5hb933r7jbkt6mq00000gn/T/carthage-xcodebuild.Lbpiz6.log
*** Skipped building Encryptor due to the error:
Dependency "Encryptor" has no shared framework schemes

If you believe this to be an error, please file an issue with the maintainers at https://github.com/telliott99/Encryptor/issues/new
>

So at first I had an error because I didn't have "master" but there was a second one, it is important to check the box "shared" under Build schemes

:

Now:

> carthage update
*** Fetching Encryptor
*** Checking out Encryptor at "bf155b9f4334ecc1f78ebcd357762eda8ebdbff6"
*** xcodebuild output can be found in /var/folders/1l/d7lmw_ln5hb933r7jbkt6mq00000gn/T/carthage-xcodebuild.t4Q2Vh.log
*** Building scheme "Encryptor" in Encryptor.xcodeproj
>


The compiled libraries are placed in folders under UseEncryptor/Carthage/, but we need to add them to the project.

For example, by dragging from the Finder window (in /Build) into the shared libraries thingie in Xcode.

Now just add this to the AppDelegate:



Debug window:

key:
pw: mypassphrase
data: b7c673d78aa3363fd1b1be53672be05f6462991e
salt: 698e91585662
iv:
3356a1155a40b509788bad7897e6434f


It works! It will also work for local files, as long as they are git repositories; e.g. the Cartfile could say:

git "file:///Users/telliott_admin/Swift-Frameworks/Encryptor" "master"

CommonCrypto4

This is the last post about CommonCrypto. I just wanted to mention that I converted Encryptor into a framework. It is still on github.

I also wrotesome command line utilities in Swift that use it. That project is here.

You can checkout the README which explains usage.

Sunday, December 13, 2015

CommonCrypto3

This is a brief note about a big project (at least for a one-day thing). I finished a Cocoa app that implements basic AES-mode encryption and decryption from the CommonCrypto library. It does not do any I/O.

For now, you can just watch it run in the debugger, using pre-formed messages. But it can handle messages that are larger than a single block by breaking the data into blocks and encrypting/decrypting each one.

One nice thing is the BinaryData class, which implements some functionality around a [UInt8] including the Indexable and CustomStringConvertible protocols, and a convenience initializer that takes a String representing binary data.



BinaryData is a class because it has a derived class Key, which implements key "stretching" from CommonCrypto.

At the very end, I ran into trouble because I did not really understand the CBC protocol.

When encrypting, the output ciphertext becomes the initialization vector for the next round. But when decrypting, the input (which is also the ciphertext) becomes the initialization vector for the next round.

Here is the output for a test:


pw: my secret
salt: 3356ec169bb6
msgText: a much longer and still really big secret
61206d756368206c6f6e67657220616e64207374696c6c207265616c6c792062696720736563726574
encryptMany
encrypt round: 1
encryptOneChunk
msgLen: 16
msg:
61206d756368206c6f6e67657220616e
keyLen: 16
iv:
39131435ae3d5bbf2e300ab5edddc8c9
status: 0
result:
55bd582296f708842e5d0833e3673a99

encrypt round: 2
encryptOneChunk
msgLen: 16
msg:
64207374696c6c207265616c6c792062
keyLen: 16
iv:
55bd582296f708842e5d0833e3673a99
status: 0
result:
ded208434eb0a4e753e6cdf1c41da54c

encrypt round: 3
encryptOneChunk
msgLen: 16
msg:
69672073656372657400000000000000
keyLen: 16
iv:
ded208434eb0a4e753e6cdf1c41da54c
status: 0
result:
66e7cb3ba1b51a0d657edad13de97b37

cipherData: 55bd582296f708842e5d0833e3673a99ded208434eb0a4e753e6cdf1c41da54c66e7cb3ba1b51a0d657edad13de97b37

decryptMany
decryptOneChunk
data:
55bd582296f708842e5d0833e3673a99
keyLen: 16
iv:
39131435ae3d5bbf2e300ab5edddc8c9
status: 0
result:
61206d756368206c6f6e67657220616e

decryptOneChunk
data:
ded208434eb0a4e753e6cdf1c41da54c
keyLen: 16
iv:
55bd582296f708842e5d0833e3673a99
status: 0
result:
64207374696c6c207265616c6c792062

decryptOneChunk
data:
66e7cb3ba1b51a0d657edad13de97b37
keyLen: 16
iv:
ded208434eb0a4e753e6cdf1c41da54c
status: 0
result:
69672073656372657400000000000000

decryptedData: 61206d756368206c6f6e67657220616e64207374696c6c207265616c6c79206269672073656372657400000000000000
a much longer and still really big secret


Whoa... there were some bytes in the cut and pasted text that did not appear in the debug console nor in the editor here on blogger,, but did appear in the Preview. They are the null bytes used to pad the plaintext. They do not appear in the final product. Curious...

The Xcode project is on github here.

It was a world of fun, but I think I am done with CommonCrypto for now.