mdevcamp 2016 - zingly, or how to design multi-banking app

Post on 07-Jan-2017

317 Views

Category:

Economy & Finance

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Zingly, or how to design a multi-banking app

Petr Dvorak joshis@tweets Lime

A big change is comming …

PSD2 Legislation

Access to account information and

payment service initiation

Banking API Server

Multi-Banking Hub Services

Bank A

Ban

ksU

sers

Inte

grat

ors

Banking API Server

Bank B

Banking API Server

Bank C

Zingly

Simple, faster and more secure

mobile banking for your bank

Extra fast login with

PIN or Touch ID

Quick account

overview

Comprehensive

transaction list

Pay your friends

and family

Mobile e-commerce

payments (with SDK)

Design

There is only one chance

to do your app right…

Showing only the nice things

("dictator rule")

Architecture

Open-source

Architecture

• PowerAuth 2.0 Server

• Zingly API Server

• Zingly Multi-banking Hub

• Zingly Mobile App

• Native iOS app (Android later)

• Written in Swift 2.0

• Native PowerAuth 2.0 core (C/C++)

• Cocoapods for library management

Zingly server components play nice

with existing banking systems

PowerAuth 2.0 Server

Zingly API Server

Zingly Multi-Banking Hub

Bank A

Internet bankingB

anks

Use

rsZ

ingl

y

CoreServices

Custom API

Bank B

Custom Security and Core Services

SOAP SOAP

REST

REST + WebSockets

PowerAuth 2.0

Security

What is so hard on mobile banking apps?

Multi-banking

• Storing data from multiple banks

• Authentication to multiple banks

• Data transport security

3rd parties

• People don’t trust them

• Cannot provide huge guarantees

• Can play no, positive or negative role

… back to PowerAuth

Mobile libraries soon But I will show you today !

Authentication Secure Storage E2E Encryption

Authentication

• Secure app activation

• Activation life-cycle

• Multi-factor data signature

Authentication How to …

Step 1: Set up your app

• Application key

• Application secret

• Master Public Key

#define APP_KEY "QvTX+lSRTNNJ9zAT8bC8iw=="

#define APP_SECRET "1zNNJNgP0RBGCJWuoHwKqw=="

#define APP_MASTER_KEY "BKltWgFa0U0qlef0c9ll3y3E4lGWrFPTBvrB+gv9tQ3wIwI aEeBnonH9HuSo/6eJKhCJcse6wHXQl8bQ="

class SecurityContext { let session = PA2Session() static let sharedInstance = SecurityContext() func initSecurityContext() { let setup = PA2SessionSetup() setup.applicationKey = APP_KEY setup.applicationSecret = APP_SECRET setup.masterServerPublicKey = APP_MASTER_KEY self.session.initializeSessionWithSetup(setup) } }

Step 2: Read the "activation code"

XC651-AB231-13891-DE123

Short activation ID Activation OTP

Step 3: Securely exchange public keys

Request - POST: /pa/activation/create

{ "requestObject": { "activationName": "My iPhone", "applicationKey": "UNfS0VZX3JhbmRvbQ==", "activationIdShort": "XDA57-24TBC", "activationNonce": "hbmRvbQRUNESF9QVUJMSUNfS0VZX3J==", "applicationSignature": "SF9QRUNEVUJMSUNfS0VZX3JhbmRvbQ==", "encryptedDevicePublicKey": "RUNESF9QVUJMSUNfS0VZX3JhbmRvbQ==", "extras": "Any custom data in any format (XML, JSON, ...)" } }

let session = SecurityContext.sharedInstance.session

let step1Param = PA2ActivationStep1Param() step1Param.activationIdShort = activationIdShort step1Param.activationOtp = activationOtp let step1Result = session.startActivation(step1Param)! // if (session.lastErrorCode == PA2ErrorCode.Ok) { let activationNonce = step1Result.activationNonce let applicationSignature = step1Result.applicationSignature let encryptedDevicePublicKey = step1Result.cDevicePublicKey

Response - HTTP 200 - OK

{ "status": "OK", "responseObject": { "activationId": "c564e700-7e86-4a87-b6c8-a5a0cc89683f", "activationNonce": "vbQRUNESF9hbmRQVUJMSUNfS0VZX3J==", "ephemeralPublicKey": "MSUNfS0VZX3JhbmRvbQNESF9QVUJMSUNfS0VZX3JhbmRvbQNESF9QVUJ==", "encryptedServerPublicKey": "NESF9QVUJMSUNfS0VZX3JhbmRvbQNESF9QVUJMSUNfS0VZX3JhbmRvbQ==", "serverDataSignature": "QNESF9QVUJMSUNfS0VZX3JhbmRvbQ==" } }

let step2Param = PA2ActivationStep2Param() let response = entity.responseObject step2Param.activationId = response.activationId step2Param.ephemeralNonce = response.activationNonce step2Param.encryptedServerPublicKey = response.encryptedServerPublicKey step2Param.ephemeralPublicKey = response.ephemeralPublicKey step2Param.serverDataSignature = response.serverDataSignature let step2Result = session.validateActivationResponse(step2Param)

if (session.lastErrorCode == PA2ErrorCode.Ok) { // ... continue to next step }

Step 4: Ask user for a PIN code

• Short PIN code (4 digits) can be used

• Check for simple combinations

• Ask user to use Touch ID

Step 5: Generate keys and get session state

// we need keys for three authentication factors ... let possessionKey = session.generateSignatureUnlockKey() let biometryKey = session.generateSignatureUnlockKey()

let unlockKeys = PA2SignatureUnlockKeys() unlockKeys.biometryUnlockKey = biometryKey unlockKeys.possessionUnlockKey = possessionKey unlockKeys.userPassword = PA2Password(string: "1234") session.completeActivation(unlockKeys)

let sessionState = session.serializedState()

Step 6: Store session and keys to keychain

// KeychainAccess for Swift // created by Kishikawa Katsumi // see https://github.com/kishikawakatsumi/KeychainAccess

let keychain = Keychain(service: "com.example.myServiceId")

keychain[data: "PA_SESSION_STATE"] = sessionState keychain[data: "PA_KEY_POSSESSION"] = possessionKey do { try keychain .accessibility( .WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .TouchIDAny ) .set(biometryKey, key: "PA_KEY_BIOMETRY") } catch _ { // Error handling... } }

Step 6: Complete activation on web

12345 67890

Step 8: Sign data, make payments, heureka!

!

// Initialize session after app launch let sessionState = keychain[data: "PA_SESSION_STATE"] if (sessionState != nil) { self.session.deserializeState(sessionState!) }

PA2SignatureUnlockKeys keys; keys.possessionUnlockKey = keychain[data: "PA_KEY_POSSESSION"]

// ... ask for PIN code keys.userPassword = cc7::MakeRange("1234")

// ... or use TouchID instead of PIN like so // keys.biometryUnlockKey = keychain[data: "PA_KEY_BIOMETRY"];

// send data on server with the correct HTTP header let paHeaderName = session.httpAuthHeaderName let paHeaderValue = session.httpAuthHeaderValueForBody( data, httpMethod: "POST", uri: "/account/payment/commit", keys: keys, factor: PA2SignatureFactor_Possession_Knowledge )

X-PowerAuth-Authorization: PowerAuth pa_activation_id="7a24c6e9-48e9-43c2-ab4a-aed6270e924d", pa_application_key="Z19gyYaW5kb521fYWN0aXZ==", pa_nonce="kYjzVBB8Y0ZFabxSWbWovY==", pa_signature_type="possession_knowledge" pa_signature="46782479-37298320", pa_version="2.0"

That wasn't that hard, right?

How about multi-banking?

Many banks, one PIN code

activation id

PIN(x)

knowledge

Bank A Bank B

activation id

knowledge

activation id

PIN(x)

activation id

PIN(x)

knowledge knowledge

Bank A Bank B

Authentication Secure Storage E2E Encryption

Secure Storage

• Data encrypted with remote key

• Authentication needed

• Enables secure mobile multi-banking

PowerAuth 2.0 Server

Zingly API Server

Zingly Multi-Banking Hub

Bank A

Internet bankingB

anks

Use

rsZ

ingl

y

CoreServices

SOAP SOAP

REST

REST + WebSockets

PowerAuth 2.0 Server

Zingly API Server

Bank B

Internet banking

CoreServices

SOAP SOAP

REST

PowerAuth 2.0 Server

Zingly API Server

Zingly Multi-Banking Hub

Bank A

Internet bankingB

anks

Use

rsZ

ingl

y

CoreServices

SOAP SOAP

REST

REST + WebSockets

PowerAuth 2.0 Server

Zingly API Server

Bank B

Internet banking

CoreServices

SOAP SOAP

REST

PowerAuth 2.0 Server

PowerAuth 2.0 Server

Zingly API Server

Zingly Multi-Banking Hub

Bank A

Internet bankingB

anks

Use

rsZ

ingl

y

CoreServices

SOAP SOAP

REST

REST + WebSockets

PowerAuth 2.0 Server

Zingly API Server

Bank B

Internet banking

CoreServices

SOAP SOAP

REST

PowerAuth 2.0 Server

PowerAuth 2.0 Client

activation id

PIN(x)

activation id

PIN(x)

knowledge knowledge

PowerAuth 2.0 Server

Zingly API Server

Zingly Multi-Banking Hub

Bank A

Internet bankingB

anks

Use

rsZ

ingl

y

CoreServices

SOAP SOAP

REST

REST + WebSockets

PowerAuth 2.0 Server

Zingly API Server

Bank B

Internet banking

CoreServices

SOAP SOAP

REST

PowerAuth 2.0 Server

PowerAuth 2.0 Client

knowledge

activation id

PIN(x)

activation id

PIN(x)

activation id

PIN(x)

knowledge knowledge

PowerAuth 2.0 Server

Zingly API Server

Zingly Multi-Banking Hub

Bank A

Internet bankingB

anks

Use

rsZ

ingl

y

CoreServices

SOAP SOAP

REST

REST + WebSockets

PowerAuth 2.0 Server

Zingly API Server

Bank B

Internet banking

CoreServices

SOAP SOAP

REST

PowerAuth 2.0 Server

PowerAuth 2.0 Client SECURE VAULT

knowledge

activation id

PIN(x)

activation id

PIN(x)

activation id

PIN(x)

knowledge knowledge

Authentication Secure Storage E2E Encryption

That was nice… What's in it for me?

• Build secure apps with PowerAuth 2.0

• Mobile e-commerce with Zingly payments

• Use banking API to access banking services

• Steal code, contribute, comment, live! !

Thank you!

Petr Dvořák e-mail: petr@lime-company.eu twitter: @zinglyapp

http://zingly.cz/

Lime

top related