Commit e31bf64c authored by Drew's avatar Drew

Use Integer192Bit struct for nonce representation

parent 45c996fd
Pipeline #584 passed with stages
......@@ -6,6 +6,8 @@ This project does not follow semver.
# Unreleased
* Add genericHash for arrays
* Convert to Integer192Bit for nonce arguments. Integer192 has its own constant-time incrementation function.
* Updating to Xcode 7.2
# 1.0.6.1 - 2015-12-07
......
......@@ -85,6 +85,9 @@
3AAAC7B51B80AB40009431FC /* NaOH.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAAC7AA1B80AB40009431FC /* NaOH.framework */; };
3AAC8C7D1C1CFEEA00B82F4D /* GenericHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC8C7C1C1CFEEA00B82F4D /* GenericHash.swift */; };
3AAC8C7F1C1CFEF500B82F4D /* GenericHashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC8C7E1C1CFEF500B82F4D /* GenericHashTests.swift */; };
3AB474D51C1D988800651809 /* increment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB474D41C1D988800651809 /* increment.swift */; };
3AB474D71C1D998A00651809 /* IncrementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB474D61C1D998A00651809 /* IncrementTests.swift */; };
3AB474D91C1D9A1D00651809 /* Integer192Bit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB474D81C1D9A1D00651809 /* Integer192Bit.swift */; };
3AC7C1BF1BC157A20036FABB /* memcmp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC7C1BE1BC157A20036FABB /* memcmp.swift */; };
3AC7C1C11BC1594D0036FABB /* MemCmpTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC7C1C01BC1594D0036FABB /* MemCmpTests.swift */; };
3AD35A341C14E3FB0095BFB4 /* PublicKey+Human.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD35A331C14E3FB0095BFB4 /* PublicKey+Human.swift */; };
......@@ -182,6 +185,9 @@
3AAAC7BB1B80AB40009431FC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3AAC8C7C1C1CFEEA00B82F4D /* GenericHash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GenericHash.swift; sourceTree = "<group>"; };
3AAC8C7E1C1CFEF500B82F4D /* GenericHashTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GenericHashTests.swift; sourceTree = "<group>"; };
3AB474D41C1D988800651809 /* increment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = increment.swift; sourceTree = "<group>"; };
3AB474D61C1D998A00651809 /* IncrementTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IncrementTests.swift; sourceTree = "<group>"; };
3AB474D81C1D9A1D00651809 /* Integer192Bit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Integer192Bit.swift; sourceTree = "<group>"; };
3AC7C1BE1BC157A20036FABB /* memcmp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = memcmp.swift; sourceTree = "<group>"; };
3AC7C1C01BC1594D0036FABB /* MemCmpTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemCmpTests.swift; sourceTree = "<group>"; };
3AD35A331C14E3FB0095BFB4 /* PublicKey+Human.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PublicKey+Human.swift"; sourceTree = "<group>"; };
......@@ -245,6 +251,8 @@
3AC7C1BE1BC157A20036FABB /* memcmp.swift */,
3AD35A331C14E3FB0095BFB4 /* PublicKey+Human.swift */,
3AAC8C7C1C1CFEEA00B82F4D /* GenericHash.swift */,
3AB474D41C1D988800651809 /* increment.swift */,
3AB474D81C1D9A1D00651809 /* Integer192Bit.swift */,
);
path = NaOH;
sourceTree = "<group>";
......@@ -262,6 +270,7 @@
3A2AF84D1B95B52500A3BEF3 /* CryptoStreamTests.swift */,
3AC7C1C01BC1594D0036FABB /* MemCmpTests.swift */,
3AAC8C7E1C1CFEF500B82F4D /* GenericHashTests.swift */,
3AB474D61C1D998A00651809 /* IncrementTests.swift */,
);
path = NaOHTests;
sourceTree = "<group>";
......@@ -521,6 +530,7 @@
buildActionMask = 2147483647;
files = (
3A2AF84C1B95B3A400A3BEF3 /* crypto_stream_chacha20.swift in Sources */,
3AB474D51C1D988800651809 /* increment.swift in Sources */,
3AAC8C7D1C1CFEEA00B82F4D /* GenericHash.swift in Sources */,
3A1922131B811DD50092C6B1 /* Key+Zeroing.swift in Sources */,
3A8ED35C1BB27E6E00164375 /* Random.swift in Sources */,
......@@ -533,6 +543,7 @@
3AC7C1BF1BC157A20036FABB /* memcmp.swift in Sources */,
3A526F6B1B80AC130092BA60 /* SwiftAPI.swift in Sources */,
3A526F6C1B80AC130092BA60 /* Key.swift in Sources */,
3AB474D91C1D9A1D00651809 /* Integer192Bit.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -547,6 +558,7 @@
3A2AF84E1B95B52500A3BEF3 /* CryptoStreamTests.swift in Sources */,
3A526FDF1B80AD4F0092BA60 /* CryptoSecretBoxTests.swift in Sources */,
3A1922041B810A7B0092C6B1 /* KeyFileTests.swift in Sources */,
3AB474D71C1D998A00651809 /* IncrementTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
//
// Integer192Bit.swift
// NaOH
//
// Created by Drew Crawford on 12/13/15.
// Copyright © 2015 DrewCrawfordApps. All rights reserved.
// This file is part of NaOH. It is subject to the license terms in the LICENSE
// file found in the top level of this distribution
// No part of NaOH, including this file, may be copied, modified,
// propagated, or distributed except according to the terms contained
// in the LICENSE file.
import Foundation
public struct Integer192Bit {
public var byteRepresentation: [UInt8]
public init(zeroed: Bool) {
precondition(24 == crypto_box_NONCEBYTES)
precondition(24 == crypto_secretbox_NONCEBYTES)
byteRepresentation = [UInt8](count: 24, repeatedValue: 0)
}
public init(random: Bool) {
precondition(24 == crypto_box_NONCEBYTES)
precondition(24 == crypto_secretbox_NONCEBYTES)
byteRepresentation = sodium_random(24)
}
public init(array: [UInt8]) {
precondition(24 == crypto_box_NONCEBYTES)
precondition(24 == crypto_secretbox_NONCEBYTES)
precondition(array.count == 24)
self.byteRepresentation = array
}
public mutating func increment() {
byteRepresentation.constantTimeIncrement()
}
}
\ No newline at end of file
......@@ -12,44 +12,46 @@
import Foundation
public func crypto_box_nonce() -> [UInt8] {
return sodium_random(Int(crypto_box_NONCEBYTES))
public func crypto_box_nonce() -> Integer192Bit {
return Integer192Bit(random: true)
}
/**This is like crypto_secretbox, but it appends the nonce to the end of the ciphertext
- note: The idea is that you don't have to send the nonce separately.
*/
public func crypto_box_appendnonce(plaintext: [UInt8], to: PublicKey, from: Key, nonce: [UInt8] = crypto_box_nonce()) throws -> [UInt8] {
public func crypto_box_appendnonce(plaintext: [UInt8], to: PublicKey, from: Key, nonce: Integer192Bit = crypto_box_nonce()) throws -> [UInt8] {
precondition(nonce.byteRepresentation.count == Int(crypto_box_NONCEBYTES),"Invalid nonce size \(nonce.byteRepresentation.count).")
var ciphertext = try crypto_box(plaintext, to: to, from: from, nonce: nonce)
ciphertext.appendContentsOf(nonce)
ciphertext.appendContentsOf(nonce.byteRepresentation)
return ciphertext
}
/**The companion to crypto_box_appendnonce */
public func crypto_box_open_appendnonce(var ciphertextAndNonce: [UInt8], to: Key, from: PublicKey) throws -> [UInt8] {
let ciphertext = ciphertextAndNonce[0..<ciphertextAndNonce.count - Int(crypto_box_NONCEBYTES)]
let nonce = ciphertextAndNonce[ciphertext.count..<ciphertextAndNonce.count]
return try crypto_box_open([UInt8](ciphertext), to: to, from: from, nonce: [UInt8](nonce))
let nonce = Integer192Bit(array: [UInt8](ciphertextAndNonce[ciphertext.count..<ciphertextAndNonce.count]))
return try crypto_box_open([UInt8](ciphertext), to: to, from: from, nonce: nonce)
}
public func crypto_box(var plaintext: [UInt8], to: PublicKey, from: Key, var nonce: [UInt8]) throws -> [UInt8] {
precondition(nonce.count == Int(crypto_box_NONCEBYTES),"Invalid nonce size \(nonce.count).")
public func crypto_box(var plaintext: [UInt8], to: PublicKey, from: Key, var nonce: Integer192Bit) throws -> [UInt8] {
precondition(nonce.byteRepresentation.count == Int(crypto_box_NONCEBYTES),"Invalid nonce size \(nonce.byteRepresentation.count).")
var ciphertext = [UInt8](count: Int(crypto_box_macbytes()) + plaintext.count, repeatedValue: 0)
try! from.unlock()
defer { try! from.lock() }
if crypto_box_easy(&ciphertext, &plaintext, UInt64(plaintext.count), &nonce, to.bytes, from.addr) != 0 {
if crypto_box_easy(&ciphertext, &plaintext, UInt64(plaintext.count), &nonce.byteRepresentation, to.bytes, from.addr) != 0 {
throw NaOHError.CryptoBoxError
}
return ciphertext
}
public func crypto_box_open(var ciphertext: [UInt8], to: Key, from: PublicKey, var nonce: [UInt8]) throws -> [UInt8] {
precondition(nonce.count == Int(crypto_box_NONCEBYTES))
public func crypto_box_open(var ciphertext: [UInt8], to: Key, from: PublicKey, var nonce: Integer192Bit) throws -> [UInt8] {
precondition(nonce.byteRepresentation.count == Int(crypto_box_NONCEBYTES))
var plaintext = [UInt8](count: ciphertext.count - crypto_box_macbytes(), repeatedValue: 0)
try! to.unlock()
defer { try! to.lock() }
if crypto_box_open_easy(&plaintext, &ciphertext, UInt64(ciphertext.count), &nonce, from.bytes, to.addr) != 0 {
if crypto_box_open_easy(&plaintext, &ciphertext, UInt64(ciphertext.count), &nonce.byteRepresentation, from.bytes, to.addr) != 0 {
throw NaOHError.CryptoBoxError
}
return plaintext
......
......@@ -16,37 +16,37 @@ public let crypto_secretbox_NONCESIZE = Int(crypto_secretbox_NONCEBYTES)
/**This is like crypto_secretbox, but it appends the nonce to the end of the ciphertext
- note: The idea is that you don't have to send the nonce separately.*/
public func crypto_secretbox_appendnonce(message: [UInt8], key: Key, nonce: [UInt8] = sodium_random(Int(crypto_secretbox_NONCEBYTES))) throws -> [UInt8] {
public func crypto_secretbox_appendnonce(message: [UInt8], key: Key, nonce: Integer192Bit = Integer192Bit(random: true)) throws -> [UInt8] {
var ciphertext = try crypto_secretbox(message, key: key, nonce: nonce)
ciphertext.appendContentsOf(nonce)
ciphertext.appendContentsOf(nonce.byteRepresentation)
return ciphertext
}
/**The companion to crypto_secretbox_appendnonce */
public func crypto_secretbox_open_appendnonce(ciphertextAndNonce: [UInt8], key: Key) throws -> [UInt8] {
let ciphertext = ciphertextAndNonce[0..<ciphertextAndNonce.count - Int(crypto_secretbox_NONCEBYTES)]
let nonce = ciphertextAndNonce[ciphertext.count..<ciphertextAndNonce.count]
return try crypto_secretbox_open([UInt8](ciphertext), key: key, nonce: [UInt8](nonce))
let nonce = Integer192Bit(array: [UInt8](ciphertextAndNonce[ciphertext.count..<ciphertextAndNonce.count]))
return try crypto_secretbox_open([UInt8](ciphertext), key: key, nonce: nonce)
}
public func crypto_secretbox(var message: [UInt8], key: Key, var nonce: [UInt8]) throws -> [UInt8] {
precondition(nonce.count == Int(crypto_secretbox_NONCEBYTES))
public func crypto_secretbox(var message: [UInt8], key: Key, var nonce: Integer192Bit) throws -> [UInt8] {
precondition(nonce.byteRepresentation.count == Int(crypto_secretbox_NONCEBYTES))
var c = [UInt8](count: crypto_secretbox_macbytes() + message.count, repeatedValue: 0)
try! key.unlock()
defer { try! key.lock() }
if crypto_secretbox_easy(&c, &message, UInt64(message.count), &nonce, key.addr) != 0 {
if crypto_secretbox_easy(&c, &message, UInt64(message.count), &nonce.byteRepresentation, key.addr) != 0 {
throw NaOHError.CryptoSecretBoxError
}
return c
}
public func crypto_secretbox_open(var ciphertext: [UInt8], key: Key, var nonce: [UInt8]) throws -> [UInt8] {
public func crypto_secretbox_open(var ciphertext: [UInt8], key: Key, var nonce: Integer192Bit) throws -> [UInt8] {
var plaintext = [UInt8](count: ciphertext.count - crypto_secretbox_macbytes(), repeatedValue: 0)
try! key.unlock()
defer { try! key.lock() }
if crypto_secretbox_open_easy(&plaintext, &ciphertext, UInt64(ciphertext.count), &nonce, key.addr) != 0 {
if crypto_secretbox_open_easy(&plaintext, &ciphertext, UInt64(ciphertext.count), &nonce.byteRepresentation, key.addr) != 0 {
throw NaOHError.CryptoSecretBoxError
}
return plaintext
......
//
// increment.swift
// NaOH
//
// Created by Drew Crawford on 12/13/15.
// Copyright © 2015 DrewCrawfordApps. All rights reserved.
// This file is part of NaOH. It is subject to the license terms in the LICENSE
// file found in the top level of this distribution
// No part of NaOH, including this file, may be copied, modified,
// propagated, or distributed except according to the terms contained
// in the LICENSE file.
import Foundation
extension Array {
/**Increments an array of UInt8 (interpreted as an arbitrarily-long unsigned number) in a way resistant to timing attacks. */
mutating func constantTimeIncrement() {
//fix this in Swift 3?
precondition(Element.self == UInt8.self, "Unexpected element \(Element.self); only implemented for UInt8")
withUnsafeMutableBufferPointer { (ptr) -> () in
let convertedPtr: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer(ptr.baseAddress)
sodium_increment(convertedPtr, ptr.count)
}
}
}
......@@ -17,7 +17,7 @@ import XCTest
class CryptoBoxTests :XCTestCase {
private let knownPlaintext : [UInt8] = [0,1,2]
private let notVeryNonce : [UInt8] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]
private let notVeryNonce = Integer192Bit(array: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23])
private let knownCiphertext : [UInt8] = [211, 170, 214, 228, 186, 238, 171, 198, 216, 148, 136, 65, 140, 6, 22, 100, 5, 32, 23]
......
......@@ -13,7 +13,7 @@ import XCTest
@testable import NaOH
class CryptoSecretBoxTests : XCTestCase {
private let NotReallyNonce: [UInt8] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
private let NotReallyNonce = Integer192Bit(array: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24])
private let known_ciphertext: [UInt8] = [238,208,130,110,75,188,8,14,80,51,115,51,112,13,233,240,85,118,104]
private let known_plaintext: [UInt8] = [0,1,2]
func testEncrypt() {
......
//
// IncrementTests.swift
// NaOH
//
// Created by Drew Crawford on 12/13/15.
// Copyright © 2015 DrewCrawfordApps. All rights reserved.
//
import Foundation
import XCTest
@testable import NaOH
class IncrementTestsTests : XCTestCase {
func testInteger192Bit() {
var i = Integer192Bit(zeroed: true)
XCTAssert(i.byteRepresentation == [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
i.increment()
XCTAssert(i.byteRepresentation == [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
for _ in 0..<254 {
i.increment()
}
XCTAssert(i.byteRepresentation == [255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
i.increment()
XCTAssert(i.byteRepresentation == [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
for _ in 0..<255 {
i.increment()
}
XCTAssert(i.byteRepresentation == [255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
i.increment()
XCTAssert(i.byteRepresentation == [0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment