Identity Key QR verification

• this plumbs in the QR verification for iOS, both scanning contact and having your fingerprint scanned.

Reviewed-by: @FredericJacobs
pull/1/head
Christine Corbett 10 years ago committed by Frederic Jacobs
parent f67e0d13f0
commit 6b4f339d7e

@ -282,6 +282,8 @@
A1A018531805C60D00A052A6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A091169C9E5E00537ABF /* CoreGraphics.framework */; };
A1C32D5017A06538000A904E /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4F17A06537000A904E /* AddressBookUI.framework */; };
A1C32D5117A06544000A904E /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; };
A56977911A351BC400173BF2 /* ScanIdentityBarcodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */; };
A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */; };
AA0C8E498E2046B0B81EEE6E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; };
B6019E971A2492AB001118DF /* NSDate+millisecondTimeStamp.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6019E961A2492AB001118DF /* NSDate+millisecondTimeStamp.mm */; };
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */ = {isa = PBXBuildFile; fileRef = B60C16641988999D00E97A6C /* VersionMigrations.m */; };
@ -858,6 +860,10 @@
A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
A1C32D4F17A06537000A904E /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
A1FDCBEE16DAA6C300868894 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
A569778D1A351BC400173BF2 /* ScanIdentityBarcodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanIdentityBarcodeViewController.h; sourceTree = "<group>"; };
A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanIdentityBarcodeViewController.m; sourceTree = "<group>"; };
A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PresentIdentityQRCodeViewController.m; sourceTree = "<group>"; };
A56977901A351BC400173BF2 /* PresentIdentityQRCodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentIdentityQRCodeViewController.h; sourceTree = "<group>"; };
B6019E951A2492AB001118DF /* NSDate+millisecondTimeStamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+millisecondTimeStamp.h"; sourceTree = "<group>"; };
B6019E961A2492AB001118DF /* NSDate+millisecondTimeStamp.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDate+millisecondTimeStamp.mm"; sourceTree = "<group>"; };
B60C16631988999D00E97A6C /* VersionMigrations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionMigrations.h; sourceTree = "<group>"; };
@ -2590,6 +2596,10 @@
FC3196321A08142D0094C78E /* Signals */ = {
isa = PBXGroup;
children = (
A569778D1A351BC400173BF2 /* ScanIdentityBarcodeViewController.h */,
A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */,
A56977901A351BC400173BF2 /* PresentIdentityQRCodeViewController.h */,
A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */,
B62D53F41A23CC8B009AAF82 /* TSMessageAdapters */,
FC3196281A067D8F0094C78E /* MessageComposeTableViewController.h */,
FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */,
@ -3001,6 +3011,7 @@
76EB063E18170B33006006FC /* Operation.m in Sources */,
76EB05F618170B33006006FC /* CallConnectUtil.m in Sources */,
76EB061218170B33006006FC /* LoggingUtil.m in Sources */,
A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */,
76EB060E18170B33006006FC /* DecayingSampleEstimator.m in Sources */,
76EB05BA18170B33006006FC /* CommitPacket.m in Sources */,
76EB060218170B33006006FC /* InitiatorSessionDescriptor.m in Sources */,
@ -3042,6 +3053,7 @@
E197B61618BBEC1A00F073E5 /* StretchFactorController.m in Sources */,
FCFD257F1A154B2C00F4C644 /* RegistrationViewController.m in Sources */,
76EB065018170B34006006FC /* DialerViewController.m in Sources */,
A56977911A351BC400173BF2 /* ScanIdentityBarcodeViewController.m in Sources */,
701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */,
76EB062218170B33006006FC /* CyclicalBuffer.m in Sources */,
76EB063C18170B33006006FC /* NumberUtil.m in Sources */,

File diff suppressed because it is too large Load Diff

@ -45,5 +45,5 @@
{
return [UIColor colorWithRed:195.f/255.f green:0 blue:22.f/255.f alpha:1.f];
}
@end

@ -26,4 +26,13 @@
@property (nonatomic, strong) IBOutlet UIButton * closeButton;
@property (nonatomic, strong) IBOutlet UIButton * shredMessagesAndContactButton;
// returns my public identity key as NSData
-(NSData*) getMyPublicIdentityKey;
// returns recipient's public identity key as NSData
-(NSData*) getTheirPublicIdentityKey;
// This is called when the recipient's public key is verified. Later can be used to mark as such if we want a step above TOFU in UX.
- (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue;
// Just a cancelation of the user's request to verify reciepient fingerprint or have their fingerprint verified by recipient
- (IBAction)unwindCancel:(UIStoryboardSegue *)segue;
@end

@ -15,6 +15,9 @@
#import "DJWActionSheet.h"
#import "TSStorageManager.h"
#import "TSStorageManager+IdentityKeyStore.h"
#import "PresentIdentityQRCodeViewController.h"
#import "ScanIdentityBarcodeViewController.h"
#include "NSData+Base64.h"
#import "TSFingerprintGenerator.h"
@ -57,6 +60,15 @@
// Dispose of any resources that can be recreated.
}
-(NSData*) getMyPublicIdentityKey {
return [[TSStorageManager sharedManager] identityKeyPair].publicKey;
}
-(NSData*) getTheirPublicIdentityKey {
return [[TSStorageManager sharedManager] identityKeyForRecipientId:self.thread.contactIdentifier];
}
#pragma mark - Initializers
- (void)initializeImageViews
{
@ -99,11 +111,31 @@
}];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:@"PresentIdentityQRCodeViewSegue"]){
[segue.destinationViewController setIdentityKey:[[self getMyPublicIdentityKey] prependKeyType]];
}
else if([[segue identifier] isEqualToString:@"ScanIdentityBarcodeViewSegue"]){
[segue.destinationViewController setIdentityKey:[[self getTheirPublicIdentityKey] prependKeyType]];
}
}
- (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue{
// Can later be used to mark identity key as verified if we want step above TOFU in UX
}
- (IBAction)unwindCancel:(UIStoryboardSegue *)segue{
NSLog(@"action cancelled");
// Can later be used to mark identity key as verified if we want step above TOFU in UX
}
#pragma mark - Shredding & Deleting
- (void)shredAndDelete
{
- (void)shredAndDelete {
#warning unimplemented: shredAndDelete
}
@end

@ -0,0 +1,15 @@
//
// PresentIdentityQRCodeViewController.h
// Signal-iOS
//
// Created by Christine Corbett Moran on 3/30/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface PresentIdentityQRCodeViewController : UIViewController
@property(nonatomic,strong) IBOutlet UIImageView* qrCodeView;
@property(nonatomic,strong) NSData* identityKey;
@end

@ -0,0 +1,75 @@
//
// PresentIdentityQRCodeViewController.m
// Signal-iOS
//
// Created by Christine Corbett Moran on 3/30/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "PresentIdentityQRCodeViewController.h"
#import "NSData+Base64.h"
@implementation PresentIdentityQRCodeViewController
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void) viewDidLoad {
[super viewDidLoad];
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setDefaults];
[filter setValue:[[self.identityKey base64EncodedString] dataUsingEncoding:NSUTF8StringEncoding] forKey:@"inputMessage"];
CIImage *outputImage = [filter outputImage];
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *image = [UIImage imageWithCGImage:cgImage scale:1. orientation:UIImageOrientationUp];
// Resize without interpolating
UIImage *resized = [self resizeImage:image withQuality:kCGInterpolationNone rate:5.0];
self.qrCodeView.image = resized;
CGImageRelease(cgImage);
}
#pragma mark - Action
- (IBAction)closeButtonAction:(id)sender
{
[UIView animateWithDuration:0.6 delay:0. options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.view setAlpha:0];
} completion:^(BOOL succeeded){
[self dismissViewControllerAnimated:YES completion:nil];
}];
}
#pragma mark - Private
- (UIImage *)resizeImage:(UIImage *)image withQuality:(CGInterpolationQuality)quality rate:(CGFloat)rate {
UIImage *resized = nil;
CGFloat width = image.size.width * rate;
CGFloat height = image.size.height * rate;
UIGraphicsBeginImageContext(CGSizeMake(width, height));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, quality);
[image drawInRect:CGRectMake(0, 0, width, height)];
resized = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resized;
}
@end

@ -0,0 +1,22 @@
//
// ScanIdentityBarcodeViewController.h
// Signal-iOS
//
// Created by Christine Corbett Moran on 3/29/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface ScanIdentityBarcodeViewController : UIViewController<AVCaptureMetadataOutputObjectsDelegate>
@property(nonatomic,strong) AVCaptureSession *session;
@property(nonatomic,strong) AVCaptureDevice *device;
@property(nonatomic,strong) AVCaptureDeviceInput *input;
@property(nonatomic,strong) AVCaptureMetadataOutput *output;
@property(nonatomic,strong) AVCaptureVideoPreviewLayer *prevLayer;
@property(nonatomic,strong) UIView *highlightView;
@property(nonatomic,strong) UILabel *label;
@property(nonatomic,strong) NSData *identityKey;
@end

@ -0,0 +1,124 @@
//
// ScanIdentityBarcodeViewController.m
// Signal-iOS
//
// Created by Christine Corbett Moran on 3/29/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "ScanIdentityBarcodeViewController.h"
#import "NSData+Base64.h"
#import "NSData+hexString.h"
@implementation ScanIdentityBarcodeViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Scan key";
self.highlightView = [[UIView alloc] init];
self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
self.highlightView.layer.borderColor = [UIColor greenColor].CGColor;
self.highlightView.layer.borderWidth = 4;
[self.view addSubview:self.highlightView];
self.label = [[UILabel alloc] init];
self.label.frame = CGRectMake(0, self.view.bounds.size.height - 40, self.view.bounds.size.width, 40);
self.label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
self.label.backgroundColor = [UIColor colorWithWhite:0.15 alpha:0.65];
self.label.textColor = [UIColor whiteColor];
self.label.textAlignment = NSTextAlignmentCenter;
self.label.text = @"(none)";
[self.view addSubview:self.label];
self.session = [[AVCaptureSession alloc] init];
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
if (self.input) {
[self.session addInput:self.input];
} else {
NSLog(@"Error: %@", error);
}
self.output = [[AVCaptureMetadataOutput alloc] init];
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[self.session addOutput:self.output];
self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes];
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.prevLayer.frame = self.view.bounds;
self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:self.prevLayer];
[self.session startRunning];
[self.view bringSubviewToFront:self.highlightView];
[self.view bringSubviewToFront:self.label];
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
CGRect highlightViewRect = CGRectZero;
AVMetadataMachineReadableCodeObject *barCodeObject;
NSString *detectionString = nil;
NSArray *barCodeTypes = @[AVMetadataObjectTypeQRCode];
for (AVMetadataObject *metadata in metadataObjects) {
NSLog(@"metadata %@",metadata);
for (NSString *type in barCodeTypes) {
if ([metadata.type isEqualToString:type]) {
barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
highlightViewRect = barCodeObject.bounds;
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
break;
}
}
if (detectionString != nil) {
self.label.text = detectionString;
NSData* detectionData = [NSData dataFromBase64String:detectionString];
if([detectionData isEqualToData:self.identityKey]) {
self.label.text = @"verified!";
}
else {
self.label.text = @"identity keys do not match";
}
[self.session stopRunning];
break;
}
else {
self.label.text = @"searching...";
}
}
if([self.label.text isEqualToString:@"verified!"]) {
[self performSegueWithIdentifier:@"UnwindToIdentityKeyWasVerifiedSegue" sender:self];
}
self.highlightView.frame = highlightViewRect;
}
#pragma mark - Action
- (IBAction)closeButtonAction:(id)sender
{
[UIView animateWithDuration:0.6 delay:0. options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.view setAlpha:0];
} completion:^(BOOL succeeded){
[self dismissViewControllerAnimated:YES completion:nil];
}];
}
@end

@ -15,7 +15,6 @@
#define ME_MESSAGE_IDENTIFIER @"Me";
@interface TSMessageAdapter : NSObject <JSQMessageData>
+ (instancetype)messageViewDataWithInteraction:(TSInteraction*)interaction inThread:(TSThread*)thread;

Loading…
Cancel
Save