|
| 1 | +// |
| 2 | +// ECCTests.m |
| 3 | +// AxolotlKit |
| 4 | +// |
| 5 | +// Created by Frederic Jacobs on 21/09/14. |
| 6 | +// Copyright (c) 2014 Frederic Jacobs. All rights reserved. |
| 7 | +// |
| 8 | + |
| 9 | +#import <UIKit/UIKit.h> |
| 10 | +#import <XCTest/XCTest.h> |
| 11 | + |
| 12 | +#import <25519/Curve25519.h> |
| 13 | +#import <25519/Ed25519.h> |
| 14 | + |
| 15 | +const Byte DJB_TYPE = 0x05; |
| 16 | + |
| 17 | +@implementation ECKeyPair (testing) |
| 18 | + |
| 19 | ++(ECKeyPair*)keyPairWithPrivateKey:(NSData*)privateKey publicKey:(NSData*)publicKey{ |
| 20 | + |
| 21 | + if ([privateKey length] == 33) { |
| 22 | + privateKey = [privateKey subdataWithRange:NSMakeRange(1, 32)]; |
| 23 | + } |
| 24 | + |
| 25 | + if (([publicKey length] == 33)) { |
| 26 | + if ([[publicKey subdataWithRange:NSMakeRange(0, 1)] isEqualToData:[NSData dataWithBytes:&DJB_TYPE length:1]]) { |
| 27 | + publicKey = [publicKey subdataWithRange:NSMakeRange(1, 32)]; |
| 28 | + } |
| 29 | + } |
| 30 | + |
| 31 | + if ([privateKey length] != ECCKeyLength && [publicKey length] != ECCKeyLength) { |
| 32 | + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Public or Private key is not required size" userInfo:@{@"PrivateKey":privateKey, @"Public Key":publicKey}]; |
| 33 | + } |
| 34 | + |
| 35 | + ECKeyPair *keyPair = [ECKeyPair new]; |
| 36 | + memcpy(keyPair->publicKey, [publicKey bytes], ECCKeyLength); |
| 37 | + memcpy(keyPair->privateKey, [privateKey bytes], ECCKeyLength); |
| 38 | + |
| 39 | + return keyPair; |
| 40 | +} |
| 41 | + |
| 42 | +@end |
| 43 | + |
| 44 | +@interface ECCTests : XCTestCase |
| 45 | + |
| 46 | +@end |
| 47 | + |
| 48 | +@implementation ECCTests |
| 49 | + |
| 50 | +- (void)setUp { |
| 51 | + [super setUp]; |
| 52 | +} |
| 53 | + |
| 54 | +- (void)tearDown { |
| 55 | + // Put teardown code here. This method is called after the invocation of each test method in the class. |
| 56 | + [super tearDown]; |
| 57 | +} |
| 58 | + |
| 59 | +- (void)testKeyAgreement{ |
| 60 | + |
| 61 | + Byte alicePublicBytes[] = {(Byte) 0x05, (Byte) 0x1b, (Byte) 0xb7, (Byte) 0x59, (Byte) 0x66, |
| 62 | + (Byte) 0xf2, (Byte) 0xe9, (Byte) 0x3a, (Byte) 0x36, (Byte) 0x91, |
| 63 | + (Byte) 0xdf, (Byte) 0xff, (Byte) 0x94, (Byte) 0x2b, (Byte) 0xb2, |
| 64 | + (Byte) 0xa4, (Byte) 0x66, (Byte) 0xa1, (Byte) 0xc0, (Byte) 0x8b, |
| 65 | + (Byte) 0x8d, (Byte) 0x78, (Byte) 0xca, (Byte) 0x3f, (Byte) 0x4d, |
| 66 | + (Byte) 0x6d, (Byte) 0xf8, (Byte) 0xb8, (Byte) 0xbf, (Byte) 0xa2, |
| 67 | + (Byte) 0xe4, (Byte) 0xee, (Byte) 0x28}; |
| 68 | + |
| 69 | + NSData *alicePublicKey = [NSData dataWithBytes:alicePublicBytes length:33]; |
| 70 | + |
| 71 | + Byte alicePrivateBytes [] = {(Byte) 0xc8, (Byte) 0x06, (Byte) 0x43, (Byte) 0x9d, (Byte) 0xc9, |
| 72 | + (Byte) 0xd2, (Byte) 0xc4, (Byte) 0x76, (Byte) 0xff, (Byte) 0xed, |
| 73 | + (Byte) 0x8f, (Byte) 0x25, (Byte) 0x80, (Byte) 0xc0, (Byte) 0x88, |
| 74 | + (Byte) 0x8d, (Byte) 0x58, (Byte) 0xab, (Byte) 0x40, (Byte) 0x6b, |
| 75 | + (Byte) 0xf7, (Byte) 0xae, (Byte) 0x36, (Byte) 0x98, (Byte) 0x87, |
| 76 | + (Byte) 0x90, (Byte) 0x21, (Byte) 0xb9, (Byte) 0x6b, (Byte) 0xb4, |
| 77 | + (Byte) 0xbf, (Byte) 0x59}; |
| 78 | + |
| 79 | + NSData *alicePrivateKey = [NSData dataWithBytes:alicePrivateBytes length:ECCKeyLength]; |
| 80 | + |
| 81 | + Byte bobPublicBytes [] = {(Byte) 0x05, (Byte) 0x65, (Byte) 0x36, (Byte) 0x14, (Byte) 0x99, |
| 82 | + (Byte) 0x3d, (Byte) 0x2b, (Byte) 0x15, (Byte) 0xee, (Byte) 0x9e, |
| 83 | + (Byte) 0x5f, (Byte) 0xd3, (Byte) 0xd8, (Byte) 0x6c, (Byte) 0xe7, |
| 84 | + (Byte) 0x19, (Byte) 0xef, (Byte) 0x4e, (Byte) 0xc1, (Byte) 0xda, |
| 85 | + (Byte) 0xae, (Byte) 0x18, (Byte) 0x86, (Byte) 0xa8, (Byte) 0x7b, |
| 86 | + (Byte) 0x3f, (Byte) 0x5f, (Byte) 0xa9, (Byte) 0x56, (Byte) 0x5a, |
| 87 | + (Byte) 0x27, (Byte) 0xa2, (Byte) 0x2f}; |
| 88 | + |
| 89 | + NSData *bobPublicKey = [NSData dataWithBytes:bobPublicBytes length:33]; |
| 90 | + |
| 91 | + Byte bobPrivateBytes [] = {(Byte) 0xb0, (Byte) 0x3b, (Byte) 0x34, (Byte) 0xc3, (Byte) 0x3a, |
| 92 | + (Byte) 0x1c, (Byte) 0x44, (Byte) 0xf2, (Byte) 0x25, (Byte) 0xb6, |
| 93 | + (Byte) 0x62, (Byte) 0xd2, (Byte) 0xbf, (Byte) 0x48, (Byte) 0x59, |
| 94 | + (Byte) 0xb8, (Byte) 0x13, (Byte) 0x54, (Byte) 0x11, (Byte) 0xfa, |
| 95 | + (Byte) 0x7b, (Byte) 0x03, (Byte) 0x86, (Byte) 0xd4, (Byte) 0x5f, |
| 96 | + (Byte) 0xb7, (Byte) 0x5d, (Byte) 0xc5, (Byte) 0xb9, (Byte) 0x1b, |
| 97 | + (Byte) 0x44, (Byte) 0x66}; |
| 98 | + |
| 99 | + NSData *bobPrivateKey = [NSData dataWithBytes:bobPrivateBytes length:ECCKeyLength]; |
| 100 | + |
| 101 | + Byte sharedBytes [] = {(Byte) 0x32, (Byte) 0x5f, (Byte) 0x23, (Byte) 0x93, (Byte) 0x28, |
| 102 | + (Byte) 0x94, (Byte) 0x1c, (Byte) 0xed, (Byte) 0x6e, (Byte) 0x67, |
| 103 | + (Byte) 0x3b, (Byte) 0x86, (Byte) 0xba, (Byte) 0x41, (Byte) 0x01, |
| 104 | + (Byte) 0x74, (Byte) 0x48, (Byte) 0xe9, (Byte) 0x9b, (Byte) 0x64, |
| 105 | + (Byte) 0x9a, (Byte) 0x9c, (Byte) 0x38, (Byte) 0x06, (Byte) 0xc1, |
| 106 | + (Byte) 0xdd, (Byte) 0x7c, (Byte) 0xa4, (Byte) 0xc4, (Byte) 0x77, |
| 107 | + (Byte) 0xe6, (Byte) 0x29}; |
| 108 | + |
| 109 | + NSData *sharedSecret = [NSData dataWithBytes:sharedBytes length:32]; |
| 110 | + |
| 111 | + ECKeyPair *aliceKeyPair = [ECKeyPair keyPairWithPrivateKey:alicePrivateKey publicKey:alicePublicKey]; |
| 112 | + ECKeyPair *bobKeyPair = [ECKeyPair keyPairWithPrivateKey:bobPrivateKey publicKey:bobPublicKey]; |
| 113 | + |
| 114 | + NSData *aliceShared = [Curve25519 generateSharedSecretFromPublicKey:[bobKeyPair publicKey] andKeyPair:aliceKeyPair]; |
| 115 | + NSData *bobShared = [Curve25519 generateSharedSecretFromPublicKey:[aliceKeyPair publicKey] andKeyPair:bobKeyPair]; |
| 116 | + |
| 117 | + XCTAssert([aliceShared isEqualToData:sharedSecret], @"Alice's shared secret is equal to the expected one."); |
| 118 | + XCTAssert([bobShared isEqualToData:sharedSecret], @"Bob's shared secret is equal to the expected one."); |
| 119 | +} |
| 120 | + |
| 121 | +- (void)testRandomKeyAgreements{ |
| 122 | + for (int i=0;i<100;i++) { |
| 123 | + ECKeyPair *aliceKeyPair = [Curve25519 generateKeyPair]; |
| 124 | + ECKeyPair *bobKeyPair = [Curve25519 generateKeyPair]; |
| 125 | + |
| 126 | + XCTAssert([[Curve25519 generateSharedSecretFromPublicKey:[aliceKeyPair publicKey] andKeyPair:bobKeyPair] isEqualToData:[Curve25519 generateSharedSecretFromPublicKey:[bobKeyPair publicKey] andKeyPair:aliceKeyPair]], @"Randomly generated keypairs produce same shared secret."); |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +- (void)testSignatures{ |
| 131 | + Byte aliceIdentityPrivate [] = {(Byte)0xc0, (Byte)0x97, (Byte)0x24, (Byte)0x84, (Byte)0x12, |
| 132 | + (Byte)0xe5, (Byte)0x8b, (Byte)0xf0, (Byte)0x5d, (Byte)0xf4, |
| 133 | + (Byte)0x87, (Byte)0x96, (Byte)0x82, (Byte)0x05, (Byte)0x13, |
| 134 | + (Byte)0x27, (Byte)0x94, (Byte)0x17, (Byte)0x8e, (Byte)0x36, |
| 135 | + (Byte)0x76, (Byte)0x37, (Byte)0xf5, (Byte)0x81, (Byte)0x8f, |
| 136 | + (Byte)0x81, (Byte)0xe0, (Byte)0xe6, (Byte)0xce, (Byte)0x73, |
| 137 | + (Byte)0xe8, (Byte)0x65}; |
| 138 | + |
| 139 | + Byte aliceIdentityPublic [] = {(Byte)0x05, (Byte)0xab, (Byte)0x7e, (Byte)0x71, (Byte)0x7d, |
| 140 | + (Byte)0x4a, (Byte)0x16, (Byte)0x3b, (Byte)0x7d, (Byte)0x9a, |
| 141 | + (Byte)0x1d, (Byte)0x80, (Byte)0x71, (Byte)0xdf, (Byte)0xe9, |
| 142 | + (Byte)0xdc, (Byte)0xf8, (Byte)0xcd, (Byte)0xcd, (Byte)0x1c, |
| 143 | + (Byte)0xea, (Byte)0x33, (Byte)0x39, (Byte)0xb6, (Byte)0x35, |
| 144 | + (Byte)0x6b, (Byte)0xe8, (Byte)0x4d, (Byte)0x88, (Byte)0x7e, |
| 145 | + (Byte)0x32, (Byte)0x2c, (Byte)0x64}; |
| 146 | + |
| 147 | + Byte aliceEphemeralPublic [] = {(Byte)0x05, (Byte)0xed, (Byte)0xce, (Byte)0x9d, (Byte)0x9c, |
| 148 | + (Byte)0x41, (Byte)0x5c, (Byte)0xa7, (Byte)0x8c, (Byte)0xb7, |
| 149 | + (Byte)0x25, (Byte)0x2e, (Byte)0x72, (Byte)0xc2, (Byte)0xc4, |
| 150 | + (Byte)0xa5, (Byte)0x54, (Byte)0xd3, (Byte)0xeb, (Byte)0x29, |
| 151 | + (Byte)0x48, (Byte)0x5a, (Byte)0x0e, (Byte)0x1d, (Byte)0x50, |
| 152 | + (Byte)0x31, (Byte)0x18, (Byte)0xd1, (Byte)0xa8, (Byte)0x2d, |
| 153 | + (Byte)0x99, (Byte)0xfb, (Byte)0x4a}; |
| 154 | + |
| 155 | + Byte aliceSignature [] = {(Byte)0x5d, (Byte)0xe8, (Byte)0x8c, (Byte)0xa9, (Byte)0xa8, |
| 156 | + (Byte)0x9b, (Byte)0x4a, (Byte)0x11, (Byte)0x5d, (Byte)0xa7, |
| 157 | + (Byte)0x91, (Byte)0x09, (Byte)0xc6, (Byte)0x7c, (Byte)0x9c, |
| 158 | + (Byte)0x74, (Byte)0x64, (Byte)0xa3, (Byte)0xe4, (Byte)0x18, |
| 159 | + (Byte)0x02, (Byte)0x74, (Byte)0xf1, (Byte)0xcb, (Byte)0x8c, |
| 160 | + (Byte)0x63, (Byte)0xc2, (Byte)0x98, (Byte)0x4e, (Byte)0x28, |
| 161 | + (Byte)0x6d, (Byte)0xfb, (Byte)0xed, (Byte)0xe8, (Byte)0x2d, |
| 162 | + (Byte)0xeb, (Byte)0x9d, (Byte)0xcd, (Byte)0x9f, (Byte)0xae, |
| 163 | + (Byte)0x0b, (Byte)0xfb, (Byte)0xb8, (Byte)0x21, (Byte)0x56, |
| 164 | + (Byte)0x9b, (Byte)0x3d, (Byte)0x90, (Byte)0x01, (Byte)0xbd, |
| 165 | + (Byte)0x81, (Byte)0x30, (Byte)0xcd, (Byte)0x11, (Byte)0xd4, |
| 166 | + (Byte)0x86, (Byte)0xce, (Byte)0xf0, (Byte)0x47, (Byte)0xbd, |
| 167 | + (Byte)0x60, (Byte)0xb8, (Byte)0x6e, (Byte)0x88}; |
| 168 | + |
| 169 | + |
| 170 | + NSData *alicePublic = [NSData dataWithBytes:aliceIdentityPublic length:33]; |
| 171 | + alicePublic = [alicePublic subdataWithRange:NSMakeRange(1, 32)]; |
| 172 | + NSData *ephemPublic = [NSData dataWithBytes:aliceEphemeralPublic length:33]; |
| 173 | + |
| 174 | + NSData *signature = [NSData dataWithBytes:aliceSignature length:ECCSignatureLength]; |
| 175 | + |
| 176 | + if (![Ed25519 verifySignature:signature publicKey:alicePublic data:ephemPublic]) { |
| 177 | + XCTAssert(FALSE, @"Sig verification failed!"); |
| 178 | + } |
| 179 | + |
| 180 | + for (int i=0;i<[signature length];i++) { |
| 181 | + |
| 182 | + NSMutableData *modifiedSignature = [signature mutableCopy]; |
| 183 | + |
| 184 | + Byte replacedByte; |
| 185 | + |
| 186 | + [modifiedSignature getBytes:&replacedByte range:NSMakeRange(i, 1)]; |
| 187 | + |
| 188 | + replacedByte ^= 0x01; |
| 189 | + |
| 190 | + [modifiedSignature replaceBytesInRange:NSMakeRange(i, 1) withBytes:&replacedByte length:1]; |
| 191 | + |
| 192 | + if ([Ed25519 verifySignature:modifiedSignature publicKey:alicePublic data:ephemPublic]) { |
| 193 | + XCTAssert(FALSE, @"Modified signature shouldn't be verified correctly"); |
| 194 | + } |
| 195 | + } |
| 196 | + |
| 197 | +} |
| 198 | + |
| 199 | +- (void)testSignatureOverflow{ |
| 200 | + ECKeyPair *keys = [Curve25519 generateKeyPair]; |
| 201 | + Byte message [4096] = {}; |
| 202 | + NSData *data = [NSData dataWithBytes:&message length:4096]; |
| 203 | + |
| 204 | + @try { |
| 205 | + NSData *signature = [Ed25519 sign:data withKeyPair:keys]; |
| 206 | + XCTAssert(FALSE, @"Signature algorithm should have thrown on overflow"); |
| 207 | + } |
| 208 | + @catch (NSException *exception) { |
| 209 | + XCTAssert(TRUE, @"All good"); |
| 210 | + } |
| 211 | +} |
| 212 | + |
| 213 | + |
| 214 | + |
| 215 | +@end |
0 commit comments