ECDH Shared Secret does not match

Hi,


I am trying to perform Diffie Hellman Key exchange between an iPad App and a microcontroller. I have successfully performed DH Key exchange between the microcontroller and PCs running .Net and PCs running Java using BouncyCastle. The particular DH I am using is ECDH curve secP256r1. For some reason I am unable to get the shared secret generated in iOS to match the shared secret generated in my microcontroller.


XCode version is 9.0.1. iOS version in iPad is 10.3 and MacOS is 10.12.6 Sierra.


Code snippet for ECDH is below. The 32 bytes in shared_secret did not match the 32 bytes in my microcontroller. I've checked before and after the SHA256 hash in my microcontroller.


Please help. Thank you.


-Yan



#define DH_PUBLIC_KEY_SIZE 64

Byte m_dh_public_key[DH_PUBLIC_KEY_SIZE+1];

SecKeyRef m_privateKey;

bool m_is_peripheral_key_rcvd = false;

Byte m_dh_peripheral_public_key[DH_PUBLIC_KEY_SIZE+1];

Byte m_dh_shared_secret[DH_PUBLIC_KEY_SIZE/2];



-(Byte *)GenerateDHKeyPair

{

NSData *tag = [@"DH.Keys" dataUsingEncoding:NSUTF8StringEncoding];

NSDictionary *p_attributes =

@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,

(id)kSecAttrKeySizeInBits: @256,

(id)kSecPrivateKeyAttrs:

@{ (id)kSecAttrIsPermanent: @YES,

(id)kSecAttrApplicationTag: tag,

},

};


CFErrorRef error = NULL;

m_privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)p_attributes,

&error);


if (m_privateKey == NULL)

{

// Handle the error

}

else

{

SecKeyRef publicKey = SecKeyCopyPublicKey(m_privateKey);

if (publicKey == NULL)

{

// Handle the error

}

NSData* keyData = (NSData*)CFBridgingRelease( // ARC takes ownership

SecKeyCopyExternalRepresentation(publicKey, &error)

);

memcpy(m_dh_public_key, [keyData bytes], 65);

}

return(m_dh_public_key);

}



- (void)SendPublicKey

{

Byte *p_public_key = [self GenerateDHKeyPair];

m_is_peripheral_key_rcvd = false;


//build host key message

BLEMsgHostPublicKey_t host_key_msg;

host_key_msg.msg_hdr.msg_id = MESSAGE_BASE_EVENT + EVENT_HOST_PUBLIC_KEY;

host_key_msg.msg_hdr.msg_body_sz = sizeof(host_key_msg.host_key);


// first byte of key blob is header - skip it. Only copy key itself (x and y)

memcpy((uint8_t *)host_key_msg.host_key.key, p_public_key + 1, sizeof(host_key_msg.host_key));


// Send Key To external device

[self SendData:(uint8_t *)&host_key_msg wNumBytes:sizeof(host_key_msg)];

}



- (void)HandlePeripheralPublicKey: (uint8_t *)m_rcvd_msg_ptr

{

memcpy(m_dh_peripheral_public_key + 1, m_rcvd_msg_ptr, sizeof(m_dh_peripheral_public_key) - 1);

m_dh_peripheral_public_key[0] = m_dh_public_key[0]; // one byte of header

m_is_peripheral_key_rcvd = true;

NSData *peripheral_pub_key = [NSData dataWithBytes:m_dh_peripheral_public_key length:sizeof(m_dh_peripheral_public_key)];


// transform rcvd key into SecKey format

NSDictionary *p_pub_key_attr =

@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,

(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,

(id)kSecAttrKeySizeInBits: @256,

};



CFErrorRef error = NULL;

SecKeyRef public_key = SecKeyCreateWithData((__bridge CFDataRef)peripheral_pub_key,

(__bridge CFDictionaryRef)p_pub_key_attr, &error);



NSDictionary *p_dh_options =

@{ (id)kSecKeyKeyExchangeParameterRequestedSize: @32,

};


CFDataRef shared_secret;

if(m_privateKey != NULL)

// generate shared secret

shared_secret = SecKeyCopyKeyExchangeResult(m_privateKey, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256, public_key,

(__bridge CFDictionaryRef)p_dh_options, &error);



NSData* keyData = (NSData*)CFBridgingRelease(shared_secret);

memcpy(m_dh_shared_secret, [keyData bytes], 32);

}

Answered by yanqil in 277745022

I ended up ditching the Security Framework and used a C-based open source ECDH module instead. After that, using the CommonCrypto library to perform SHA hashing and AES encryption was suprisingly easy. As I already have a solution, I will not open an incident. Thank you for the response.

ECDH Shared Secret does not match

If no one else chimes in here I recommend that you open a DTS tech support incident for this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

I ended up ditching the Security Framework and used a C-based open source ECDH module instead. After that, using the CommonCrypto library to perform SHA hashing and AES encryption was suprisingly easy. As I already have a solution, I will not open an incident. Thank you for the response.

ECDH Shared Secret does not match
 
 
Q