Crypto createPublicKey Algorithm parameter, what to take in

Former Member
Former Member

Hello. I am using the Cryptology module to perform ECDH key exchange. My question is primarily on how or what to pass in for the first parameter, algorithm. The byte array received from the peripheral device, their public key. I am trying to turn it into a key so that I can add it to the KeyAgreement.

using Toybox.Cryptology as Crypto;

I am doing garminPK = Crypto.createPublicKey(Crypto.KEY_PAIR_ELLIPTIC_CURVE_SEC256R1, otherPKbytes);

But I am getting fatal errors of types (

     1  Details: "Could not find symbol 'KEY_PAIR_ELLIPTIC_CURVE_SECP256R1'"                       

     2  Error: Unhandled Exception                                                                                                   // No details, but same line when trying the numeric value instead of the enum (1)

     3  Error: Symbol Not Found Error
        Details: 'Failed invoking <symbol>' 

     )

Just trying variations of the two KEY_PAIR enums and the hardcoded 0 or 1. Am I passing something completely wrong? Any details help please. Thank you

  • You should be able to catch the exception you're seeing in case #2 and get some information from it (type of exception, the exception message string, stack trace). My guess is that it is failing because the key bytes are not valid for creating a key of the specified type, most likely because the endianness of the input data is incorrect; it looks like we expect little-endian data.

    Here is a quick snippet that I used to verify things are working...

    using Toybox.Cryptography;
    using Toybox.System;
    using Toybox.Lang;
    
    
    try {
        var publicKeyBytesBob = [
            0xC9, 0x50, 0x53, 0xBC, 0x7C, 0x8C, 0x9A, 0xF2,
            0xC3, 0x93, 0x9A, 0x50, 0x6B, 0x7E, 0xC8, 0x5C,
            0xFC, 0x41, 0x27, 0x95, 0x5D, 0x7D, 0x67, 0xD2,
            0x85, 0x38, 0x10, 0x4D, 0x28, 0xF8, 0x98, 0x92,
            0xD5, 0xFB, 0xE3, 0x78, 0x78, 0xE5, 0x04, 0x89,
            0x70, 0xF8, 0x84, 0xCB, 0xE2, 0x3A, 0xA9, 0xB2,
            0x23, 0xBC, 0xC6, 0x4C, 0x85, 0x3D, 0xDD, 0xF3,
            0x1A, 0x88, 0x29, 0x3F, 0x7F, 0x43, 0x9A, 0x33
        ]b;
    
        var publicKeyBob = Cryptography.createPublicKey(Cryptography.KEY_PAIR_ELLIPTIC_CURVE_SECP256R1, publicKeyBytesBob);
    
        var privateKeyBytesAlice = [
            0x2E, 0x62, 0x6F, 0x62, 0x20, 0x6F, 0x74, 0x20,
            0x72, 0x65, 0x74, 0x74, 0x65, 0x6C, 0x20, 0x65,
            0x74, 0x61, 0x76, 0x69, 0x72, 0x70, 0x20, 0x61,
            0x20, 0x73, 0x69, 0x20, 0x73, 0x69, 0x68, 0x74
        ]b;
    
        var keyPairAlice = new Cryptography.KeyPair({
            :algorithm => Cryptography.KEY_PAIR_ELLIPTIC_CURVE_SECP256R1,
            :privateKey => privateKeyBytesAlice
        });
    
        var keyAgreementAlice = new Cryptography.KeyAgreement({
            :protocol => Cryptography.KEY_AGREEMENT_ECDH,
            :privateKey => keyPairAlice.getPrivateKey()
        });
    
        keyAgreementAlice.addKey(publicKeyBob);
    
        var secretKeyAliceAndBob = keyAgreementAlice.generateSecret();
    
        System.println(secretKeyAliceAndBob);
    }
    catch(e instanceof Lang.InvalidValueException) {
        System.println(e.getErrorMessage());
        e.printStackTrace();
    }

  • Former Member
    0 Former Member over 4 years ago in reply to Travis.ConnectIQ

    Hey Travis, thank you for the reply. You're exactly right. Initially it was upset that I hadn't put Crypto.KEY_AGREEMENT, but after that I attributed the problem to import, but it was actually the bytes. When sending the bytes I didn't realize the read/write (characteristics) was limited to only 20 bytes so it was sending a error 13 (1 and 12 for no resources/failed, I think) whereas my other data pieces happened to be under 20 bytes. 

    I have to come up with some manner of packet reformation on the reads to create the full public key from the other side. 

  • Former Member
    0 Former Member over 4 years ago in reply to Travis.ConnectIQ

    Does the 256 require 64 bytes exactly? I'm converting from a PublicKey object read from Android. I flipped it from Big Endian to Little Endian. 

    var androidPublicKey = 
    {
    0x64 , 0x76 , 0x9F , 0xDE , 0xE2 , 0x10 , 0x0A , 0x8F , 
    0xD5 , 0x56 , 0x4F , 0x57 , 0x75 , 0xD3 , 0x47 , 0xA9 , 
    0xCF , 0x22 , 0xF6 , 0x42 , 0xC1 , 0xCE , 0xF4 , 0xFB , 
    0x73 , 0x60 , 0x22 , 0x16 , 0xBC , 0x13 , 0xC0 , 0x41 ,
    0x26 , 0x05 , 0xA1 , 0x5B , 0x5F , 0xF9 , 0x3E , 0x22 , 
    0x18 , 0xC2 , 0x40 , 0x68 , 0xC3 , 0x3F , 0x5E , 0x4E , 
    0xAA , 0x90 , 0x01 , 0x4F , 0xE1 , 0xD4 , 0x0A , 0xF8 ,
    0xCA , 0xA1 , 0x07 , 0x82 , 0x37 , 0x75 , 0x0E , 0xF6
    }
    
    // in a try-catch
    androidPK = Crypto.createPublicKey(Crypto.KEY_PAIR_ELLIPTIC_CURVE_SECP256R1, androidPKbytes);


    This just being an example 64 byte key that failed in Little Endian. I received the bytes through a queue and formed the packet. Printing the byte array does print it in decimal, but I assume that's intentional.

  • Does the 256 require 64 bytes exactly?

    Yes.

    Printing the byte array does print it in decimal, but I assume that's intentional.

    Yes.