EMV® 3-D Secure—SDK Technical Guide

v2.1.0 Best Practices
3-D Secure

EMV<sup>®</sup> 3-D Secure SDK Technical Guide Version 2.1.0 October 2017

countries. EMV 3-D Secure SDK Technical Guide v2.1.0 Legal Notice

/ 64 This document summarizes EMVCo’s present plans for evaluation services and related policies and is subject to change by EMVCo at any time. This document does not create any binding obligations upon EMVCo or any third party regarding the subject matter of this document, which obligations will exist, if at all, only to the extent set forth in separate written agreements executed by EMVCo or such third parties. In the absence of such a written agreement, no product provider, test laboratory or any other third party should rely on this document, and EMVCo shall not be liable for any such reliance. No product provider, test laboratory or other third party may refer to a product, service or facility as EMVCo approved, in form or in substance, nor otherwise state or imply that EMVCo (or any agent of EMVCo) has in whole or part approved a product provider, test laboratory or other third party or its products, services, or facilities, except to the extent and subject to the terms, conditions and restrictions expressly set forth in a written agreement with EMVCo, or in an approval letter, compliance certificate or similar document issued by EMVCo. All other references to EMVCo approval are strictly prohibited by EMVCo. Under no circumstances should EMVCo approvals, when granted, be construed to imply any endorsement or warranty regarding the security, functionality, quality, or performance of any particular product or service, and no party shall state or imply anything to the contrary. EMVCo specifically disclaims any and all representations and warranties with respect to products that have received evaluations or approvals, and to the evaluation process generally, including, without limitation, any implied warranties of merchantability, fitness for purpose or noninfringement. All warranties, rights and remedies relating to products and services that have undergone evaluation by EMVCo are provided solely by the parties selling or otherwise providing such products or services, and not by EMVCo, and EMVCo will have no liability whatsoever in connection with such products and services. This document is provided "AS IS" without warranties of any kind, and EMVCo neither assumes nor accepts any liability for any errors or omissions contained in this document. EMVCO DISCLAIMS ALL REPRESENTATIONS AND WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT, AS TO THIS DOCUMENT. EMVCo makes no representations or warranties with respect to intellectual property rights of any third parties in or in relation to this document. EMVCo undertakes no responsibility to determine whether any implementation of this document may violate, infringe, or otherwise exercise the patent, copyright, trademark, trade secret, know-how, or other intellectual property rights of third parties, and thus any person who implements any part of this document should consult an intellectual property attorney before any such implementation. Without limiting the foregoing, this document may provide for the use of public key encryption and other technology, which may be the subject matter of patents in several countries. Any party seeking to implement this document is solely responsible for determining whether its activities require a license to any such technology, including for patents on public key encryption technology. EMVCo shall not be liable under any theory for any party's infringement of any intellectual property rights in connection with this document.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

1. 1. 1. 1. 1. 1. 1.6.1 1.6.2 1.6. 2. 2. 2.2.1 2.2.2 2.2.3 2.2.4 2.2. Authentication request (i.e. Decision point  Frictionless flow vs. 2. 2.3. 2.3. 2. 2.4. 2.4. 3. 3.1.1 3.1.2 3.1. 3. 3.2.1 3.2.2 3.2. 3. 3.3. 3.3.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 3.3.3 3.3.4 3.3.5 3.3. 3. 3.4.1 3.4.2 3.4. 3. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 3.5. 4. 4. 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2. 4. 4. 4.4. 4.4. 5. 5.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 5.2. 5.2. 5. 5.3. 5.3. 5. 5. 5.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 1 Introduction

/ 71 1.1 About EMV 3-D Secure SDK Technical Guide This document is the technical guide of the EMV 3-D Secure SDK. Its purpose is to give additional insight to the implementation of the described SDK based on the specification documentation. EMV 3-D Secure Core Protocol and Specification describes how authentication transactions would happen in a mobile application environment. From an implementation perspective, the merchant’s mobile application is separated from the 3-D Secure SDK (Software Development Kit that is also referred to as "SDK" in this document), which would implement most of the 3D Secure functionality (collection of device data, communication towards the ACS, and user authentication) in the mobile device. Furthermore, the Core Specification describes the functionality and requirements for the 3DS Requestor in general. During the spring and summer of 2016, EMVCo conducted a project where an SDK was implemented as proof-of-concept based on the newly-created 3-D Secure specifications. The implementation and screen captures appearing in this document are from the aforementioned project. While this document discusses the SDK in the context of a mobile device, similar SDK can be implemented for other devices such as smart TV’s and tablets. Furthermore, this document may refer to the 3DS Requestor as "Merchant" and talk about "Merchant Application". In addition, the document also uses the term "Purchase transaction" to describe the whole transaction that the cardholder is performing. This is just for clarity reasons and not intended to limit the transactions to those dealing with a purchase. For a more precise terminology, please see the Core Specification page. If not otherwise stated, this document uses screen captures from an Android implementation of the SDK.

1.2 Overview and Scope This document describes the implementation aspect of 3-D Secure SDK. The purpose of this document is to provide insight on implementation of an SDK, not to serve as an explicit guide. The examples and code samples presented in this document are meant to give guidance and overview on how a certain functionality e.g. encryption can be implemented. The following diagram describes the bigger picture of the environment that the SDK is part of. On a high level, the SDK’s functionality consists of the following:

  • Initialization of the transaction and receiving required information from the 3DS Requestor App
  • Collection of device data, encrypting it, and returning the encrypted data to 3DS Requestor App
  • Handling of the user interface (challenge-related views, providing the progress view object to 3DS Requestor App) during the transaction based on the given parameters and information (UICustomization, CRes)
  • Perform the challenge step of the 3-D Secure transaction countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 / 71
  • Secure and encrypted communication between SDK and ACS (CReq/CRes, challenge) In a 3-D Secure transaction, there are parts that the SDK does not cover. As the 3DS Requestor App starts the authentication transaction, it communicates directly with the 3DS Requestor and 3DS Server. This communication is not in the scope of the SDK and thus not in this document.

1.3 Other systems described in this document The SDK is a component in the 3DS Requestor Environment and it interfaces with other 3-D Secure systems. The figure below illustrates the big picture of 3-D Secure and how the SDK fits in the big picture. For more detailed information on the topic, see the chapter 2 of the Core Specification. The systems that are relevant from the SDK’s viewpoint are marked with orange color and described below. Figure 1 3-D Secure components 3DS Requestor App 3DS Requestor App is a mobile application in the cardholder’s mobile device. The 3DS Requestor App has the SDK in it to perform the 3-D Secure functionality.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 For more information about the 3DS Requestor App, see chapter 5 Merchant Implementation. 3DS Server The 3DS Server is a part of the 3DS Requestor environment that implements the 3-D Secure protocol and functionality. Its main purpose is to act as a Merchant side component of the transaction, communicating towards Directory Server and ACS (AReq/ARes and RReq/RRes) and providing the 3DS Requestor App with the required information to perform the transaction (transaction status, does the transaction require challenge, needed information for SDK to proceed with CReq/CRes). The communication between the 3DS Requestor App and the 3DS Server is not in the scope of 3-D Secure or this document. Each vendor may implement their own proprietary communication between the two components as long as it meets the security requirements described in the Core Specification. ACS The ACS is the only 3-D Secure component that the SDK communicates with. ACS serves as the Issuer side component implementing the 3-D Secure protocol. From an SDK viewpoint, the ACS performs the challenge functionality and communicates with the SDK using CReq and CRes messages. The communication between the SDK and ACS is secured and encrypted. For more details on ACS in 3-D Secure transactions, see the Core Specification.

1.4 Audience This document is intended for use by Implementers who want to develop a 3-D Secure SDK. This document gives examples of the implementation and should be read together with 3-D Secure Core Specification and 3-D Secure SDK Specification 1.5 Related documents The reader should be familiar with the following documents that this document refers to and the 3-D Secure protocol and transaction flow in general. The documentation below is referred as "Specifications". EMV 3-D Secure Protocol and Core Specification The EMV 3-D Secure Protocol and Core Specification (referred to as "Core Specification") describes the details of the 3-D Secure protocol, infrastructure, components, and specifies the requirements for each component and their interaction.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 EMV 3-D Secure SDK Specification The EMV 3-D Secure SDK Specification (version 2.1.0, referred to as "SDK Specification") describes the requirements and functionality of the 3-D Secure SDK. The document has detailed descriptions of the classes and methods that the SDK offers to the 3DS Requestor App to perform its tasks. EMV 3-D Secure SDK – Device information The EMV 3-D Secure SDK – Device Information describes the device identification parameters that shall be collected by the 3DS SDK.

1.6 Notational Conventions 1.6.1

Definitions

For the definition of the terms used in this specification, refer to Table 1.3: Definitions in the EMV 3-D Secure Protocol and Core Functions Specification.

1.6.2 Abbreviations This document uses the same abbreviations as the Core Specification. Abbreviation 3DS 3DS SDK ACS AReq ARes AV BIN CA CA DS CReq CRes DS ECI Table 1 Abbreviations

Description

Three Domain Secure Three Domain Secure Software Development Kit Access Control Server Authentication Request Authentication Response Authentication Value Bank Identification Number Certificate Authority Certificate Authority Directory Server Challenge Request Challenge Response Directory Server Electronic Commerce Indicator

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 Abbreviation JSON MAC NPA NVP OOB PA OTP SDK TLS URL UUID Description JavaScript Object Notation Message Authentication Code Non-Payment Authentication NameValuePair Out-of-Band Payment Authentication One-time Passcode Software Development Kit Transport Layer Security Uniform Resource Locator Universally Unique Identifier

/ 71 1.6.3 Terminology and Conventions The following words are used in this guide and have a specific meaning: Purchase transaction The term is used to describe the full transaction cycle from user’s viewpoint and is not intended to limit the transactions to ones where a purchase is involved. Merchant The term is used to refer to the 3DS Requestor. For clarity reasons and as an example of a 3DS Requestor, the term Merchant may be used.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 2 Implementation of the transaction flows This chapter describes the implementation of the SDK from the 3-D Secure transaction viewpoint. The content has been divided into chapters based on the flow, see the left-hand side for the phases. The implementation decisions documented in this chapter are indicative in nature and originate from the proof-of-concept implementation project conducted by EMVCo 3-D Secure Task Force in spring and summer of 2016. There may be other ways to implement the specified functionality. The 3-D Secure transaction is defined in more detail in the Core Specification and SDK Specification documents. This document references to the Core Specification where necessary. This chapter is organized to follow the transaction flow. The flow has been divided into the following chapters:

  • Chapter 2.1 SDK initiation describes the steps that the SDK takes when the 3DS Requestor App is started and the SDK initiated
  • Chapter 2.2 Frictionless flow describes the steps that the 3DS Requestor App and the SDK take during a frictionless flow. Note that parts of the 3-D Secure transaction take place outside the SDK.
  • Chapter 2.3 Challenge flow describes the steps that the 3DS Requestor App and the SDK take to perform the rest of the transaction if a challenge is required. Figure 2 3-D Secure transaction below illustrates the transaction flow on a high level. countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 Figure 2 3-D Secure transaction / 71 countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 / 71 2.1 SDK initiation The Initiation phase is executed when the 3DS Requestor App is started. It calls the initialize() –method of the SDK which performs relevant tasks and changes its status to Initialized. The initialize()-method performs the following tasks:
  • SDK settings are loaded (configuration parameters, locale, UI customization)
  • Security checks are performed (see list of security requirements in Core Specification)
  • Device data is collected for all protocol versions that the SDK supports (see 3-D Secure SDK – Device Information document)
  • Possible warnings are generated. The 3DS Requestor App may request them when needed. After a successful initialization, the SDK is ready to perform 3-D Secure transactions. For more information on the security checks performed during the initialization phase, see chapter 3.5 Implementation of Security.

2.2 Frictionless flow This chapter describes the transaction flow from start to the point where the 3DS Requestor App has the information to decide if a challenge is needed (status "C" in ARes-message) or not. If challenge is not needed, the 3DS Requestor App calls the SDK only in the beginning when the transaction is initiated and an instance of progressView is provided to the 3DS Requestor App by the SDK. Figure 3 Simplified transaction flow (Frictionless)

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 2.2.1 Transaction initiation The transaction can be initiated by the 3DS Requestor App once it has all the necessary information needed to perform the transaction. As the 3DS Requestor App initiates the 3-D Secure transaction, it should perform the following tasks:

  • Transaction instance is created (createTransaction()-method)
  • Device Data is collected and returned to the 3DS Requestor App
  • Return an instance of progressView to the 3DS Requestor App (getProgressView()- method) Do note that the Core Specification does not specify that it is the responsibility of the SDK to gather the needed information. The information that the 3DS Server needs to construct and process the AReq-message must come from a component within the 3DS Requestor Environment.

2.2.2 Device Data collection The SDK collects device data during the transaction initiation phase. All the device data required for all protocol versions supported by the SDK has to be collected during the ThreeDS2Service initialization. However, only the device data fields for the selected protocol version of the transaction should be included in the transaction getDeviceData() method. This getDeviceData() method returns the Device Data as an encrypted String. The Device Data is intended to be encrypted through the 3DS Requestor Environment and decrypted when it reaches the Directory Server in the AReq-message. The device data parameters are described in more detail in the EMV 3-D Secure SDK Device Information document. Note that terms Device Information and Device Parameters are also used for this purpose. Permissions and Device Data collection Note that the SDK may use only those permissions that the 3DS Requestor Application has requested. The SDK itself shall not request additional permissions. The SDK Specification states that there should not be any run-time prompting of permissions when the SDK performs its operations. All permissions should be granted to the application during installation or before the SDK is initiated. Collection of device data must be implemented so that the process is not stopped even though the SDK does not have the permission to collect the information, e.g. location.

2.2.3 Progress View The processing of the 3-D Secure transaction takes a few seconds. For the user experience to remain smooth, a Progress View has been specified to be displayed while the 3DS Requestor App or the SDK perform tasks in the background. The progress view is generated by the SDK. The 3DS Requestor App requests the SDK for an instance of it and displays it before starting communication to the 3DS Server (authentication request, AReq/ARes-phase). See chapter 4.2.1 for a sample implementation of the Progress View.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 2.2.4 Authentication request (i.e. the AReq/ARes-phase) This step happens during a 3-D Secure transaction but is not specified in the Specifications. The AReq/ARes-phase is a part of the 3-D Secure transaction but not in scope of the SDK. The 3DS Requestor App communicates with the 3DS Requestor Environment, which handles the phase. The SDK’s only role in this phase has to do with the device data collected in initiation phase. 3DS Requestor App receives the device data parameters from the SDK in an encrypted form. The device data is sent by the 3DS Requestor App to 3DS Server for AReq/ARes-processing. As this phase is out of the SDK’s scope and implemented by the 3DS Requestor App, see the Merchant Implementation in chapter 5 for more details.

2.2.5 Decision point  Frictionless flow vs

Challenge flow Based on the information received by the 3DS Requestor Server after the AReq/ARes-phase, the 3DS Requestor App may end the authentication transaction (Frictionless flow, status Y, A or error) or continue the transaction to Challenge (status "C" in ARes-message). If the 3-D Secure transaction is regarded as "Frictionless" (status anything but "C" in the AResmessage), the processing ends here and the SDK is not called. The 3DS Requestor App proceeds with the purchase transaction based on the information it has received from the 3DS Requestor Server. If the 3-D Secure transaction requires a challenge (status "C" in ARes-message), the 3DS Requestor App calls the SDK to perform the challenge phase.

2.3 Challenge flow From transaction viewpoint, the Challenge flow is continuation of the Frictionless flow in transactions where a challenge is needed (status "C" in ARes-message). Figure 4 Simplified transaction flow (Challenge)

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 2.3.1 Communication between SDK and ACS SDK establishes a secure connection to the ACS. The secure connection details are defined in detail in the Core Specification (Chapters 6.1.4 and 6.2.3)

  • The communication between the SDK and ACS is encrypted. For more information on the encryption and code samples, see chapter 3 Security and cryptography in this document.

2.3.2 Challenge dialogue The challenge dialogue is the most visible part of the SDK. The Core Specification defines a set of pages with their own purpose. The SDK selects the appropriate display pages based on what the CRes-message to be used in the challenge dialogue. The SDK implements two UI-types:

  • Native pages are implemented with the native UI components of the platform
  • HTML pages are implemented as a WebView component, displaying the HTML content sent by ACS Page types The SDK selects the page type depending on what the ACS has requested in CRes-message (ACS UI Type).
  • Text
  • Single select
  • Multi select
  • Out of Band
  • HTML SDK renders the page type with information provided by the ACS. Note about Out of Band In Out of Band channel the authentication itself happens in a separate application or device.

2.4 Namespace Vendor should have the EMV 3DS functionality in their own namespace according to platform conventions. 2.4.1 iOS In iOS Objective-C code this means prefixing the names according to Apple conventions described in Apple developer documentation. For more information on the topic, see https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Programming WithObjectiveC/Conventions/Conventions.html 2.4.2 Other platforms On other platforms this means using packages that belong to vendor’s namespace. For more details, see platform specific documentation and conventions on namespaces.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 3 Security and cryptography This chapter gives examples and code samples regarding the security and cryptography implementations. There are many ways to implement the functionality, the attached code samples show one way of doing it. The samples are from the proof-of-concept implementation of the EMV 3-D Secure SDK.

3.1 Device data encryption Device data encryption is defined in the Core Specification in chapter 6.2.2.1. Core Specification defines the supported algorithms as RSA-OAEP and encryption as A128CBCHS256 or A128GCM. SDK does the encryption with the directory server specific public key shipped in the app itself. Security of the stored data is discussed in chapter 3.5.14 Encryption of stored data. Here are examples of encryption on different platforms.

3.1.1 Android Proof-of-concept implementation uses Nimbus JOSE JWE library (http://connect2id.com/products/nimbus-jose-jwt). This library implements everything needed for device data encryption on SDK with reasonably high level interface. Example code can be found below. If the DS public key is an RSA key: public static String jweEncrypt(String dd, RSAPublicKey publicKey) { try { JWTClaimsSet set = JWTClaimsSet.parse(dd); EncryptedJWT jwt = new EncryptedJWT( new JWEHeader(JWEAlgorithm.RSA_OAEP, EncryptionMethod.A128CBC_HS256), set); jwt.encrypt(new RSAEncrypter(publicKey)); String result = jwt.serialize(); return result; } catch (Exception e) { } return null; } Else, if the DS public key is an EC key: public static String jweEncrypt(String dd, ECPublicKey publicKey, dsId) { KeyPair kp = null; try { JWTClaimsSet set = JWTClaimsSet.parse(dd); kp = Crypto.generateEphemeralKeyPair(); SecretKey k = Crypto.generateECDHSecret(publicKey, (ECPrivateKey)kp.getPrivate(), dsId); JWK jwk = new ECKey.Builder(ECKey.Curve.P_256, String

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 (ECPublicKey)kp.getPublic()).build(); JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.DIR, EncryptionMethod.A128CBC_HS256). ephemeralPublicKey(ECKey.parse(jwk.toJSONString())).build(); JWEObject jweObject = new JWEObject(header, new Payload(dd)); jweObject.encrypt(new DirectEncrypter(k)); String result = jweObject.serialize(); return result; } catch (Exception e) { } finally { kp = null; } return null; } 3.1.2 iOS 9 On iOS 9 platform proof-of-concept implementation does the JWE calculation directly using cryptography primitives available from commonCrypto libraries. The algorithm closely follows the description in RFC 7516. All needed components are generated, and then the actual JWE structure is filled according to the RFC. If the DS public key is an RSA key: /* Device Data encryption - create JWE given DS publicKey */ +(NSString *)createJWE:(NSString *)payload withPublicKey:(SecKeyRef)publicKey { // create secretKey for encryption NSData *secret = [self generateRandom:(KEY_SIZE*2)]; NSData *hmacKey = [secret subdataWithRange:NSMakeRange(0, KEY_SIZE)]; NSData *aesKey = [secret subdataWithRange:NSMakeRange(KEY_SIZE, KEY_SIZE)]; NSData *iv = [self generateRandom: IV_SIZE]; // create header NSString *header = @"{"enc":"A128CBC-HS256","alg":"RSA-OAEP"}"; // encrypt secretKey NSData *encryptedKey = [self rsaEncrypt:secret key:publicKey]; // encrypt payload NSData *encrypted = [self aesEncrypt:[payload dataUsingEncoding:NSUTF8StringEncoding] withKey:aesKey withIV:iv]; NSString *basePayload = [encrypted unpaddedBase64URLEncoded]; NSString *baseCEK = [encryptedKey unpaddedBase64URLEncoded]; NSString *baseHeader = [[header dataUsingEncoding:NSUTF8StringEncoding] unpaddedBase64URLEncoded]; NSString *baseIV = [iv unpaddedBase64URLEncoded]; // create auth hash NSData *hmac = [self hmac: encrypted withKey: hmacKey withIV: iv withA: [baseHeader dataUsingEncoding:NSASCIIStringEncoding]]; return [NSString stringWithFormat:@"%@.%@.%@.%@.%@", baseHeader, baseCEK, baseIV, basePayload, [[self hmacToTag: hmac] unpaddedBase64URLEncoded]]; }

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 Else, if the DS public key is an EC key: /* Device Data encryption - create JWE given DS publicKey */ +(NSString *) createJWE:(NSData *)payload withSecret: (NSData *)secret withPublicKey:(NSString *)jwk { // create header NSString *header = [NSString stringWithFormat: @"{"enc":"A128CBC-HS256","alg":"dir","epk":%@ NSLog(@"Header %@", header); }",jwk]; // encrypt payload NSData *hmacKey = [secret subdataWithRange:NSMakeRange(0, KEY_SIZE)]; NSData *aesKey = [secret subdataWithRange:NSMakeRange(KEY_SIZE, KEY_SIZE)]; NSData *iv = [self generateRandom: IV_SIZE]; NSData *encrypted = [self aesEncrypt: payload withKey: aesKey withIV: iv]; NSString *basePayload = [encrypted unpaddedBase64URLEncoded]; NSString *baseHeader = [[header dataUsingEncoding:NSUTF8StringEncoding] unpaddedBase64URLEncoded]; NSString *baseIV = [iv unpaddedBase64URLEncoded]; // create auth hash NSData *hmac = [self hmac: encrypted withKey: hmacKey withIV: iv withA: [baseHeader dataUsingEncoding:NSASCIIStringEncoding]]; return [NSString stringWithFormat:@"%@..%@.%@.%@", baseHeader, baseIV, basePayload, [[self hmacToTag: hmac] unpaddedBase64URLEncoded]]; } 3.1.3 Windows 10 Mobile Using jose-rt NuGet package: public static string JweEncryptDeviceData(string dd, string publicKeyPemBytes) { return Jwt.Encode(dd, JwaAlgorithms.RSA_OAEP, JweAlgorithms.A128CBC_HS256, JoseRT.Rsa.PublicKey.Load(publicKeyPemBytes)); } 3.2 Diffie-Hellman process When generating data needed for AReq message (when 3DS Requestor App calls getAuthenticationRequestParameters() method in Transaction interface (see 4.4 in SDK Specification)), SDK needs to generate its ephemeral keypair for Diffie-Hellman key exchange. This is defined in the Core Specification 6.2.3.1.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 3.2.1 Android On Android this is done directly using BouncyCastle: public static KeyPair generateEphemeralKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { BouncyCastleProvider provider = new BouncyCastleProvider(); ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("P-256"); KeyPairGenerator g = KeyPairGenerator.getInstance("ECDH", provider); g.initialize(ecGenSpec, new SecureRandom()); return g.generateKeyPair(); } 3.2.2 iOS 9 On iOS 9 this requires a bit more work again, especially when using Objective-C. GMEllipticCurveCrypto (https://github.com/ricmoo/GMEllipticCurveCrypto) can be used to generate the keypair. Generated public key is not yet ready to be included in the AReq message since it is not properly ASN.1 formatted. This is done in proof-of-concept implementation by hard coding the ASN.1 envelope around the key. /*! * Produces the following ASN.1 structure: * * | 0:d=0 | hl=2 | l= | 89 | cons: | SEQUENCE | | * | 2:d=1 | hl=2 | l= | 19 | cons: | SEQUENCE | | * | 4:d=2 | hl=2 | l= | 7 | prim: | OBJECT |:id-ecPublicKey | * | 13:d=2 | hl=2 | l= | 8 | prim: | OBJECT |:prime256v1 | * | 23:d=1 | hl=2 | l= | 66 | prim: | BIT | STRING | */ + (NSString*) publicKeyToProperASN1: (NSData *)publicKey { NSMutableData *asn1 = [[NSMutableData alloc]init]; char sec256r1_header[] = {0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00}; [asn1 appendBytes:sec256r1_header length:sizeof(sec256r1_header)]; [asn1 appendData: publicKey]; NSString *encoded = [asn1 base64EncodedStringWithOptions:0]; return encoded; } This method can then be used when generating the actual Ephemeral public key:... ephemeralKey = [GMEllipticCurveCrypto generateKeyPairForCurve: GMEllipticCurveSecp256r1]; [ephemeralKey setCompressedPublicKey: FALSE]; authRequestParams.sdkEphmeralPublicKey = [JWS publicKeyToProperASN1:[ephemeralKey publicKey]];...

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 3.2.3 Windows 10 Mobile using Windows.Security.Cryptography.Core; using Windows.Security.Cryptography; authParams = new AuthenticationRequestParameters(); AsymmetricKeyAlgorithmProvider p = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.Ecdsa Sha256); ephmeralKey = p.CreateKeyPairWithCurveName(EccCurveNames.NistP256); authParams.SDKEphmeralPublicKey = CryptographicBuffer.EncodeToBase64String(ephmeralKey.ExportPublicKey());

3.3 JWS signature checking When doing the second part of SDK - ACS secure channel setup (Core specification 6.2.3), SDK starts by validating signature of JWS structure in ARes.ACSSignedContent field. This field is passed to SDK through ChallengeParameters.getAcsSignedContent method call (SDK Specification 4.11.8). SDK needs to validate the signature to ensure that the data within the JWS structure has been passed unchanged from ACS to SDK. SDK has root certificate for each DS it communicates and it can use this root certificate to validate the certificate chain in JWS structure.

3.3.1 Android On Android, JWS structure validation can be done using again Nimbus JOSE implementation. The following code sample shows how it can be done give the root certificate and the JWS structure. public static String jwsValidateSignatureAndReturnBody(String jws) { JWSObject jwsObject; try { jwsObject = JWSObject.parse(jws); } catch (ParseException e) { throw new RuntimeException("JWS parsing failed"); } try { JWSVerifier verifier = null; JWSAlgorithm alg = jwsObject.getHeader().getAlgorithm(); if (alg.equals(JWSAlgorithm.PS256) || alg.equals(JWSAlgorithm.RS256)) { List x509CertChain = jwsObject.getHeader().getX509CertChain(); verifier = new RSASSAVerifier((RSAPublicKey) X509CertUtils.parse(x509CertChain.get(0).decode()).getPublicKey()); } else if (alg.equals(JWSAlgorithm.ES256)) { verifier = new ECDSAVerifier(ECKey.parse(jwsObject.getHeader().getJWK().toJSONString())); } else { // unsupported algorithm throw new RuntimeException(); } if (!jwsObject.verify(verifier)) {

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 throw new RuntimeException("JWS validation failed."); } } catch (Exception e) { throw new RuntimeException("JWS validation failed."); } return jwsObject.getPayload().toString(); }

/ 71 3.3.2 iOS 9 On iOS the situation is similar as with device data encryption, the JWS checking is implemented by using cryptography primitives from commonCrypto package, but the PS256 signature validation was implemented manually based on RFC 3447. - (BOOL) verify:(NSString *)header withPayload:(NSString *)payload withSignature:(NSData *)signature { NSString *clearHeader = [JWS base64Decode: header]; NSData *headerData = [clearHeader dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *headerContents = [JWS JSONToDictionary:headerData]; NSString *alg = headerContents[@"alg"]; //validate signature // if alg == @"E256" { NSDictionary *jwk = headerContents[@"jwk"]; NSData *xD = [JWS base64DecodeData:jwk[@"x"]]; NSData *yD = [JWS base64DecodeData:jwk[@"y"]]; NSMutableData *pk = [NSMutableData dataWithCapacity:65]; char bytesToAppend[1] = {0x04};// Uncompressed raw key [pk appendBytes:bytesToAppend length:sizeof(bytesToAppend)]; [pk appendData:xD]; [pk appendData:yD]; GMEllipticCurveCrypto *crypto = [GMEllipticCurveCrypto cryptoForCurve:GMEllipticCurveSecp256r1]; crypto.publicKey = pk; size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH; unsigned char hashBytes[hashBytesSize]; NSString *signinInput = [[NSArray arrayWithObjects: jwsHeader, payload, nil] componentsJoinedByString:@"."]; NSData *inputData = [signinInput dataUsingEncoding:NSUTF8StringEncoding]; CC_SHA256(inputData.bytes, (CC_LONG)inputData.length, hashBytes); if ([crypto verifySignature:signature forHash:[NSData dataWithBytes:hashBytes length:hashBytesSize]]) { return TRUE; } NSLog(@"JWS failed"); return FALSE; }

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 // else if alg == @"PS256" { NSArray *x5cArray = (NSArray *)headerContents[@"x5c"]; // validate the cert chain if ([self validateCertChain: x5cArray, dsRoot]) { NSLog(@"JWS cert chain invalid"); return nil; } //load X509 certificate NSData *x509cert = [JWS base64DecodeData:(NSString *)x5cArray[0]]; SecKeyRef publicKey = [JWS getX509CertPublicKey:x509cert]; if (!publicKey) { NSLog(@"JWT public key invalid"); return nil; } //implement RFC 3447 for PS256 signature validation manually } 3.3.3 Windows 10 Mobile Using BouncyCastle and jose-rt NuGet package, signature validation: public static Json GetJwsObject(string jwsData) { string[] data = jwsData.Split(new Char[] { '.' }); string h = Encoding.UTF8.GetString(CryptographicBuffer.DecodeFromBase64String(data[0]).ToArray()); Json header = Utils.CreateImpl(); header = header.Parse(h); string cert = header.GetNamedStringArray("x5c")[0]; byte[] x509 = System.Convert.FromBase64String(cert); X509CertificateParser parser = new X509CertificateParser(); X509Certificate x509Certificate = parser.ReadCertificate(x509); try { AsymmetricKeyParameter publicKey = x509Certificate.GetPublicKey(); SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey); AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPk cs1); CryptographicKey key = provider.ImportPublicKey(CryptographicBuffer.CreateFromByteArray(info.GetEn coded())); string res = Jwt.Decode(jwsData, key); return Utils.CreateImpl().Parse(res); }

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 catch (Exception e) { throw e; } } After the SDK has validated the JWS structure, it can do its second half of the Diffie-Hellman handshake defined in the Core specification 6.2.3. For this SDK has created a fresh Ephemeral keypair to be included AReq message through AuthenticationRequestParameters.getSDKEphemeralPublicKey method (SDK spec 4.12.6). Ephemeral key generation is described in the below examples.

3.3.4 Android Android does the handshake using a Concat KDF class, as defined in Section 5.8.1 of NIST.800-56A, with the parameters given by the Core Specification. The com.nimbusds.jose.crypto.ConcatKDF implementation was used as reference. public static SecretKey generateECDHSecret(ECPublicKey pub, ECPrivateKey priv, String sdkReferenceId) { try { SecretKey z = ECDH.deriveSharedSecret(pub, priv, null); ConcatKDF kdf = new ConcatKDF("SHA-256"); return kdf.deriveKey( z, 256, ConcatKDF.encodeStringData(null), ConcatKDF.encodeDataWithLength((Base64URL)null), ConcatKDF.encodeDataWithLength(Base64URL.encode(sdkReferenceId)), ConcatKDF.encodeIntData(256), ConcatKDF.encodeNoData()); } catch (Exception e1) { l.error("failed to decrypt", e1); throw new RuntimeException(); } } 3.3.5 iOS 9 On iOS, this is done using manually implementing RFC 7518 and NIST.800-56A.

3.3.6 Windows 10 Mobile Using BouncyCastle: IBuffer acsKey = CryptographicBuffer.DecodeFromBase64String(jws.GetNamedString(ProtocolConst ants.ACSEphemeralPublicKey)); secretKey = Crypto.CreateSessionKey(ephemeralKey.Export(), acsKey, sdkReferenceNumber); public static byte[] CreateSessionKey(IBuffer privateKey, IBuffer acsPublicKey, string sdkReferenceId) { AsymmetricKeyParameter publicKeyParams = PublicKeyFactory.CreateKey(acsPublicKey.ToArray());

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 AsymmetricKeyParameter privateKeyParams = PrivateKeyFactory.CreateKey(privateKey.ToArray()); IBasicAgreement agreement = AgreementUtilities.GetBasicAgreement("ECDH"); agreement.Init(privateKeyParams); BigInteger key = agreement.CalculateAgreement(publicKeyParams); // pad with leading zeroes if needed byte[] k = key.ToByteArrayUnsigned(); byte[] buffer = Enumerable.Repeat((byte)0x00, 32).ToArray(); Array.ConstrainedCopy(k, 0, buffer, (buffer.Length - k.Length), k.Length); DataWriter writer = new DataWriter(); writer.WriteBytes(buffer); IBuffer z = writer.DetachBuffer(); writer.Dispose(); ConcatKDF kdf = new ConcatKDF(HashAlgorithmNames.Sha256); return kdf.DeriveKey(JoseRT.Util.Buffer.ToBytes(z), 256, ConcatKDF.EncodeStringData(null), ConcatKDF.EncodeDataWithLength((string)null), ConcatKDF.EncodeDataWithLength(Base64Url.Encode( Encoding.UTF8.GetBytes(sdkReferenceId))), ConcatKDF.EncodeIntData(256), ConcatKDF.EncodeNoData()); } 3.4 Encryption of CReq / Decryption of CRes Once the secret key is generated in SDK, it can be used to encrypt CReq and decrypt CRes messages. In case of A128CBC-HS256 only one key is used for both directions (i.e. for both CReq encryption and for CRes decryption) whereas with A128GCM both directions have separate keys.

3.4.1 Android As with other encryption operations, this is also done with Nimbus JOSE. public byte[] encrypt(JSONObject challengeRequest) { try { final byte counter = sdkCounterStoA; JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.DIR, EncryptionMethod.A128GCM).keyID((String) challengeRequest.get(ProtocolConstants.ACSTransactionID)).build(); challengeRequest.put(ProtocolConstants.SDKCounterStoA, String.format("d",counter)); JWEObject jweObject = new JWEObject(header, new Payload(challengeRequest.toString()));

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 jweObject.encrypt(new TransactionEncrypter(Arrays.copyOfRange(secretKey.getEncoded(),0,16), counter)); byte[] bytes = jweObject.serialize().getBytes(); sdkCounterStoA ++; if (sdkCounterStoA == 0) { throw new RuntimeException("SdkCounterStoA zero"); } return bytes; } catch (Exception e) { log.info("JWE failed"); return challengeRequest.toString().getBytes(); } } The reference implementation has implemented the TransactionEncrypter-class as follows: public final class TransactionEncrypter extends com.nimbusds.jose.crypto.DirectEncrypter{ private byte counter; public TransactionEncrypter(byte[] key, KeyLengthException { super(new SecretKeySpec(key, "AES")); this.counter = counter; } byte counter) throws @Override public JWECryptoParts encrypt(JWEHeader header, byte[] clearText) throws JOSEException { JWEAlgorithm alg = header.getAlgorithm(); if (! alg.equals(JWEAlgorithm.DIR)) { throw new JOSEException("Invalid alg " + alg); } // Check key length matches encryption method EncryptionMethod enc = header.getEncryptionMethod(); if (enc.cekBitLength() != ByteUtils.bitLength(getKey().getEncoded())) { throw new KeyLengthException(enc.cekBitLength(), enc); } final Base64URL encryptedKey = null; // The second JWE part if (enc.cekBitLength() != ByteUtils.bitLength(getKey().getEncoded())) { throw new KeyLengthException("The Content Encryption Key (CEK) length for " + enc + " must be " + enc.cekBitLength() + " bits"); } // Apply compression if instructed

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 byte[] plainText = DeflateHelper.applyCompression(header, clearText); // Compose the AAD byte[] aad = AAD.compute(header); // Encrypt the plain text according to the JWE enc byte[] iv = Crypto.getGcmIvStoA(counter); AuthenticatedCipherText authCipherText; if (header.getEncryptionMethod().equals(EncryptionMethod.A128CBC_HS256)) { authCipherText = AESCBC.encryptAuthenticated( getKey(), iv, plainText, aad, getJCAContext().getContentEncryptionProvider(), getJCAContext().getMACProvider()); } else if (header.getEncryptionMethod().equals(EncryptionMethod.A128GCM)) { authCipherText = AESGCM.encrypt( getKey(), iv, plainText, aad, getJCAContext().getContentEncryptionProvider()); } else { throw new JOSEException(AlgorithmSupportMessage.unsupportedEncryptionMethod( header.getEncryptionMethod(), SUPPORTED_ENCRYPTION_METHODS)); } return new JWECryptoParts( header, encryptedKey, Base64URL.encode(iv), Base64URL.encode(authCipherText.getCipherText()), Base64URL.encode(authCipherText.getAuthenticationTag())); } } Below is an example how to implement Crypto.getGcmIvStoA() public static byte[] getGcmIvStoA(byte sdkCounterStoA) { return getGcmId((byte)0x00, sdkCounterStoA); } public static byte[] getGcmIvAtoS(byte sdkCounterAtoS) { return getGcmId((byte)0xFF, sdkCounterAtoS); } private static byte[] getGcmId(byte pad, byte counter) { byte[] iv = new byte[16]; Arrays.fill(iv, pad); iv[iv.length-1] = counter; return iv; } Decryption is also done with Nimbus JOSE.

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 try { byte[] key = secretKey.getEncoded(); JWEObject jweObject = JWEObject.parse(message); EncryptionMethod jweMethod = jweObject.getHeader().getEncryptionMethod(); if (jweMethod == EncryptionMethod.A128GCM) { key = Arrays.copyOfRange(key, key.length-16, key.length); } jweObject.decrypt(new DirectDecrypter(key)); JSONObject challengeResponse = new JSONObject(jweObject.getPayload().toString()); byte acsCounterAtoS = Byte.valueOf(challengeResponse.getString(ProtocolConstants.ACSCounterAtoS)); if (sdkCounterAtoS != acsCounterAtoS) { throw new RuntimeException("counters (" + sdkCounterAtoS + "/" + acsCounterAtoS + ")"); } sdkCounterAtoS ++; if (sdkCounterAtoS == 0) { throw new RuntimeException("SDKCounterAtoS zero"); } return challengeResponse; } catch (Exception e) { log.error("failed to decrypt", e); throw new RuntimeException(); } 3.4.2 iOS 9 On iOS this operation is again implemented manually, using crypto primitives from commonCrypto and then crafting the JSON structure by hand. One thing to note here is that A128CBC-HS256 seemed to be the only one of the algorithms mentioned in the Core Specification 6.2.3 that worked at the time of writing. +(NSString *) createJWE: (NSData *)payload withSecret: (NSData *)secret withKid: (NSString *)kid { NSData *hmacKey = [secret subdataWithRange:NSMakeRange(0, KEY_SIZE)]; NSData *aesKey = [secret subdataWithRange:NSMakeRange(KEY_SIZE, KEY_SIZE)]; NSData *iv = [self generateRandom: IV_SIZE]; // create header NSString *header = [NSString stringWithFormat: @"{"kid":"%@","enc":"A128CBC-HS256","alg":"dir"}", kid]; // encrypt payload NSData *encrypted = [self aesEncrypt: payload withKey: aesKey withIV: iv]; NSString *basePayload = [encrypted unpaddedBase64URLEncoded]; NSString *baseHeader = [[header dataUsingEncoding:NSUTF8StringEncoding] unpaddedBase64URLEncoded]; NSString *baseIV = [iv unpaddedBase64URLEncoded]; // create auth hash

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 NSData *hmac = [self hmac: encrypted withKey: hmacKey withIV: iv withA: [baseHeader dataUsingEncoding:NSASCIIStringEncoding]]; return [NSString stringWithFormat:@"%@..%@.%@.%@", baseHeader, baseIV, basePayload, [[self hmacToTag: hmac] unpaddedBase64URLEncoded]]; } After this function is called, the following checking is done: sdkCounterStoA++; if (sdkCounterStoA == 0) { NSDictionary *errorDictionary = @{ NSLocalizedDescriptionKey: @"SdkCounterStoA zero"}; NSError *error = [[NSError alloc] initWithDomain:@"MI_SDK" code:-1 userInfo:errorDictionary]; @throw error; } Decrypting example below: +(NSString *)parseJWE: (NSString *) based withSecret: (NSData *)secret { // base64 url encoding is not exactly base64... // https://tools.ietf.org/html/draft-ietf-jose-json-web-signature41#appendix-C // //NSString *based = [[jwe stringByReplacingOccurrencesOfString:@"_" withString: @"/"] stringByReplacingOccurrencesOfString:@"-" withString:@"+"]; //NSData *decodedSecret = [self base64DecodeData:secret]; NSData *hmacKey = [secret subdataWithRange:NSMakeRange(0, KEY_SIZE)]; NSData *aesKey = [secret subdataWithRange:NSMakeRange(KEY_SIZE, KEY_SIZE)]; NSArray *components = [based componentsSeparatedByString:@"."]; /* this is useful when debugging... [components enumerateObjectsUsingBlock:^(id object, NSUInteger *stop) { NSLog(@"%lu: %@", (unsigned long)idx, [object description]); }]; */ idx, BOOL // JWE contains 5 components // 1 Header // we need this to do the hmac NSString *header = [components objectAtIndex:0]; // we only support one algorithm, and we don't really need kid on this side // so this can be left here waiting for some use //NSString *clearHeader = [self base64Decode: header]; // 2 encrypted key // we don't use key, and I hate warnings, so it is commented for now //NSString *key = [components objectAtIndex:1];

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 // 3 IV NSString *iv = [components objectAtIndex:2]; NSData *decodedIV = [self base64DecodeData:iv]; // 4 payload NSString *payload = [components objectAtIndex:3]; NSData *decodedPayload = [self base64DecodeData: payload]; // 5 Tag NSString *tag = [components objectAtIndex:4]; NSData *decrypted = [self aesDecrypt: decodedPayload withKey: aesKey withIV: decodedIV]; NSString* decryptedPayload = [[NSString alloc] initWithData:decrypted encoding:NSUTF8StringEncoding]; NSData *hmac = [self hmac: decodedPayload withKey: hmacKey withIV: decodedIV withA: [header dataUsingEncoding:NSASCIIStringEncoding]]; NSString *calculatedTag = [[self hmacToTag: hmac] unpaddedBase64URLEncoded]; decryptedPayload = [decryptedPayload stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSRange r = [decryptedPayload rangeOfString:@"}" options:NSBackwardsSearch]; decryptedPayload = [decryptedPayload substringWithRange: NSMakeRange(0, r.location + 1)]; if (! [tag isEqualToString: calculatedTag]) { NSLog(@"TAG doesn't match: message = %@, calculated = %@", tag, calculatedTag); return decryptedPayload; } return decryptedPayload; } After this function is called, the following checking is done: NSError *serializationError = nil; NSLog(@"data2: %@", [[NSString alloc] initWithData:decrypted encoding:NSUTF8StringEncoding]); id json = [NSJSONSerialization JSONObjectWithData:decrypted options:0 error:&serializationError]; if (serializationError) { SDKLogE(@"Serialization error %@",serializationError); @throw serializationError; } uint8_t acsCounterAtoS = [json[KACSCounterAtoS] if (sdkCounterAtoS != acsCounterAtoS) { SDKLogE(@"counters not equal"); return nil; } intValue]; sdkCounterAtoS++; if (sdkCounterAtoS == 0) { NSDictionary *errorDictionary = @{ NSLocalizedDescriptionKey: @"SdkCounterAtoS zero"};

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 NSError *error = [[NSError alloc] initWithDomain:@"MI_SDK" code:-1 userInfo:errorDictionary]; @throw error; } 3.4.3 Windows 10 Mobile Using jose-rt NuGet package: public Json Decrypt(string message) { Part[] jweParts = Compact.Parse(message); Json jweHeader = Utils.CreateImpl().Parse(Encoding.UTF8.GetString(jweParts[0].Bytes)); string decrypted; if (jweHeader.GetNamedString("enc").Equals(JoseRT.JweAlgorithms.A128GCM)) { decrypted = Jwt.Decode(message, Arrays.FirstHalf(secretKey)); } else { decrypted = Jwt.Decode(message, secretKey); } Json challengeResponse = Utils.CreateImpl().Parse(decrypted); byte acsCounterAtoS = Convert.ToByte(challengeResponse.GetNamedString(ProtocolConstants.ACSCounte rAtoS),16); if (sdkCounterAtoS != acsCounterAtoS) { throw new Exception("counters (" + sdkCounterAtoS + "/" + acsCounterAtoS + ")"); } sdkCounterAtoS++; if (sdkCounterAtoS == 0) { throw new Exception("counter } zero"); return challengeResponse; } public string Encrypt(Json challengeRequest) { byte counter = sdkCounterStoA; DirectKeyManagement algorithm = new DirectKeyManagement(); var jwtHeader = new JsonObject { {"enc",JsonValue.CreateStringValue(JoseRT.JweAlgorithms.A128CBC_HS256) }, {"alg", JsonValue.CreateStringValue(JoseRT.JwaAlgorithms.DIR) }, {"kid", JsonValue.CreateStringValue(challengeRequest.GetNamedString(ProtocolConstan ts.ACSTransactionID)) } };

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 challengeRequest.Add(ProtocolConstants.SDKCounterStoA, Convert.ToString(counter)); Part[] keys = algorithm.WrapNewKey(256, secretKey, jwtHeader); Part cek = keys[0]; Part encryptedCek = keys[1]; Part header = Part.New(jwtHeader.Stringify()); byte[] plainText = Encoding.UTF8.GetBytes(challengeRequest.Stringify()); byte[] aad = Encoding.UTF8.GetBytes(Compact.Serialize(header)); AesCbcHmacEncryptor encryptor = new AesCbcHmacEncryptor(256); Part[] encParts = encryptor.Encrypt(aad, plainText, cek.Bytes); string encrypted = Compact.Serialize(header, encryptedCek, encParts[0], encParts[1], encParts[2]); sdkCounterStoA++; if (sdkCounterStoA == 0) { throw new Exception("counter } zero"); return encrypted; } 3.5 Implementation of Security Features The SDK implements a number of security functions that are defined in more detail in 3DS SDK specification and in PCI 3DS Security Standard. Payment Systems may also have additional requirements related to SDK security features. During SDK initialization, the SDK performs a number of security checks that are defined in Chapter 8.2 of the SDK Specification. Possible security warnings are made available to the 3DS Requestor Application. In the following chapters (3.5.1 – 3.5.5), implementation examples are given of each security check. Table 2 3DS SDK Initialization Security Checks Security Warning ID Description SW01 The device is jailbroken. Severity Level HIGH SW02 The integrity of the SDK has been tampered. HIGH SW03 An emulator is being used to run the App. HIGH SW04 A debugger is attached to the App. MEDIUM

countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0

/ 71 Security Warning ID Description SW05 The OS or the OS version is not supported. Severity Level HIGH In addition to the security checks listed above, this chapter gives implementation examples of further security features (chapters 3.5.6 – 3.5.15). The examples presented in this chapter do not fully cover the requirements but rather give guidance on how the requirements can be fulfilled. The code samples should not be used directly in production code.

3.5.1 SW01: The device is jailbroken This check shall be conducted during initialization and make the result of the checks available as a list of warnings to the 3DS Requestor App. Android On android the typical and simple way to check if root access is enabled is to look for typical root binaries such as su, and sudo binaries from binary paths, and typical root apps, such as superuser.apk. Below is an example of a possible implementation: public static final List BINARY_PATHS = Arrays.asList("/sbin/", "/system/bin/", "/system/xbin/", "/data/local/xbin/", "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/"); public static final List APK_PATHS = Arrays.asList("/system/app/"); public static String isRooted() { return findSuBinary() + findSuperuserAPK(); } public static String findSuBinary() { String s = findFileInPaths("su", BINARY_PATHS); if (s != null && s.length() &gt; 0) { return "su binary was found on paths: " + s; } return ""; } public static String findSuperuserAPK() { String s = findAPK("Superuser"); if (s != null && s.length() &gt; 0) { return "Superuser apk was found on paths: " + s; } return ""; } iOS On iOS jailbreaking can be detected multiple ways. Some of the more popular options are:

  • detecting files created during jailbreaking process (for example /private/var/tmp/cydia.log)
  • detecting symlinks of small partitions (such as /usr/include) countries. EMV<sup>®</sup> 3-D Secure SDK Technical Guide v2.1.0 / 71
  • checking API calls, for instance system() return values
  • detecting whether cydia:// scheme is available Windows 10 Mobile There is currently no way to determine if Developer Mode is turned on in the device, but "Windows.ApplicationModel.Package.Current.IsDevelopmentMode" can be used to detect if the app was installed in development mode. More information on the topic can be found on the Microsoft Developer site at: https://msdn.microsoft.com/library/windows/apps/dn175745 3.5.2 SW02: The integrity of the SDK has been tampered This check shall be conducted during initialization and make the result of the checks available as a list of warnings to the 3DS Requestor App. Android In Android, the checking of the SDK integrity can only be accomplished by implementing class consistency verification using standard Java language reflection (java.lang.reflect.*). The SDK.aar Android Java library release binary cannot be signed because you can only sign the actual application release binary. iOS In iOS, the checking of the SDK integrity can only be accomplished by implementing class consistency verification using o

Shown in part. Read the original for the full text.