2

I'm new to encryption. i want to create public seckey from data but i always get nil. Please help me. I need this public key as seckey to create a shared secrete key but i always get nil . how i can convert data to seckey?

Below are the code for refrence. I'm using swift language.

 let attributes: [String:Any] = [
        kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
        kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
        kSecAttrKeySizeInBits as String: 512,
        ]



var pubKey = publicKey2

var error1: Unmanaged<CFError>?

/// Create seckey
guard let pubSecKey = SecKeyCreateWithData((Data(bytes: publicKey2) as CFData), attributes as CFDictionary, &error1)else{
    print(error1?.takeRetainedValue().localizedDescription)
    return []
}
var error: Unmanaged<CFError>?
/// create shared key
guard let shared1 = SecKeyCopyKeyExchangeResult(LSILock.privtKey, .ecdhKeyExchangeCofactorX963SHA256, pubSecKey, keyPair, &error) else {
    return []
}

print(shared1)

Update

below are the bytes which i want to convert into seckey:

[12, 178, 30, 213, 113, 166, 59, 63, 203, 236, 182, 205, 126, 28, 81, 13, 94, 98, 67, 231, 152, 244, 180, 213, 168, 190, 237, 88, 131, 159, 173, 131, 75, 203, 51, 193, 115, 60, 36, 158, 27, 27, 174, 4, 211, 63, 25, 13, 174, 174, 64, 35, 59, 58, 151, 193, 167, 225, 13, 142, 237, 255, 25, 38]

if characteristic.uuid.uuidString == LSILock.AUTHENTICATION_KEY_EXHANGE {
                print(value)

                let hexValue = value.toHexString()
                print(hexValue)

                if let d = hexValue.lowercased().dataFromHexadecimalString() {
                    print(d.bytes)
                    LSILock.goForPrivatekeys = LSILock.goForPrivatekeys + 1

                    let dropFirst = d.bytes.dropFirst(1)
                    let dropLast = dropFirst.dropLast(3)

                        LSILock.lockPublicKey.append(contentsOf: dropLast)

                        if LSILock.goForPrivatekeys == 4{
                            LSILock.goForPrivatekeys = 0
                            let secKey = aesCTRencrytion(publicKey2: LSILock.lockPublicKey, keyPair: LSILock.keyPairs as CFDictionary)
                            print(secKey)
                            privateKeyExchange(secKey)

                        }
                }

            }
func dataFromHexadecimalString() -> Data? {
    let trimmedString = self.trimmingCharacters(in: CharacterSet(charactersIn: "<> ")).replacingOccurrences(of: " ", with: "")

    // make sure the cleaned up string consists solely of hex digits, and that we have even number of them

    let regex: NSRegularExpression?
    do {
        regex = try NSRegularExpression(pattern: "^[0-9a-f]*$", options: .caseInsensitive)
    } catch _ as NSError {
        regex = nil
    }
    let found = regex?.firstMatch(in: trimmedString, options: [], range: NSMakeRange(0, trimmedString.count))
    if found == nil || found?.range.location == NSNotFound || trimmedString.count % 2 != 0 {
        return nil
    }

    // everything ok, so now let's build NSData

    let data = NSMutableData(capacity: trimmedString.count / 2)

    for i in stride(from:0,to:trimmedString.count,by:2) {
        let start = trimmedString.index(trimmedString.startIndex, offsetBy: i)
        let end = trimmedString.index(trimmedString.startIndex, offsetBy: i+1)

        // get a sub-string with a ClosedRange
        let range = start...end

        let byteString = trimmedString[range]
        let num=UInt8(byteString.withCString { strtoul($0, nil, 16) })
        data?.append([num] as [UInt8], length: 1)
    }

    return data as Data?
}
func aesCTRencrytion( publicKey2 : [UInt8], keyPair : CFDictionary ) -> [UInt8]{
let message = "001C971A3456"
    let messageData   = message.dataFromHexadecimalString()!.bytes
print(ivData)


let attributes: [String:Any] = [
    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
    kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
    kSecAttrKeySizeInBits as String: 512,
    kSecReturnPersistentRef as String : true
    ]

var pubKey = publicKey2

var error1: Unmanaged<CFError>?

/// Create seckey
guard let pubSecKey = SecKeyCreateWithData((Data(bytes: publicKey2) as CFData), attributes as CFDictionary, &error1)else{
    print(error1?.takeRetainedValue().localizedDescription)
    return []
}



var error: Unmanaged<CFError>?
/// create shared key
guard let shared1 = SecKeyCopyKeyExchangeResult(LSILock.privtKey, .ecdhKeyExchangeCofactorX963SHA256, pubSecKey, keyPair, &error) else {
    return []
}

print(shared1)

}

Below i generate pair of keys:

func ecdhEncryption() {
        //        let privComponents = try? CC.EC.getPrivateKeyComponents(LSILock.keys!.0)
        //        let pubComponents = try? CC.EC.getPublicKeyComponents(LSILock.keys!.1)
        //
        //        let pubKey = try? CC.EC.createFromData( pubComponents!.keySize, pubComponents!.x, pubComponents!.y)
        //        print(pubKey)
        //                let pubKey1 = try? CC.EC.getPublicKeyFromPrivateKey(LSILock.keys!.0)
        //        print(pubKey1)
        //        guard let lock = LockSmartAPI.sharedInstance.getLock(lock_sn) else{return}
        //        lock.keyExchange(pubKey!)


        var publicKey = [UInt8]()
        var privateKey = [UInt8]()

        var publicKeySec, privateKeySec: SecKey?
        let keyattribute = [
            SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 32,
            kSecAttrKeyType as String: kSecAttrKeyTypeEC,
            kSecAttrKeySizeInBits as String : 256
            ] as CFDictionary
        SecKeyGeneratePair(keyattribute, &publicKeySec, &privateKeySec)

        LSILock.keyPairs = keyattribute as! [String : Any]

        var error:Unmanaged<CFError>?
        if let publicCfdata = SecKeyCopyExternalRepresentation(publicKeySec!, &error) {
            let data:Data = publicCfdata as Data

            print(data)
            let b64Key = data.base64EncodedString()
            print(b64Key)
        }

        if let privateCfdata = SecKeyCopyExternalRepresentation(privateKeySec!, &error) {
            let data:Data = privateCfdata as Data
            print(data)
            let b64Key = data.base64EncodedString()
            print(b64Key)
        }


//        guard let privateKey1 = SecKeyCreateRandomKey(keyattribute as CFDictionary, &error) else {
//            return
//        }
//        let publicKey1 = SecKeyCopyPublicKey(privateKey1)
//        print(publicKey1 as? Data ?? Data())


        //                print(publicKeySec)
        //                print(privateKeySec)

        var error1: Unmanaged<CFError>?
        let keyData = SecKeyCopyExternalRepresentation(privateKeySec!, &error1)
        let data = keyData! as Data
        var privateKeyBytes = data.bytes
        privateKeyBytes.removeFirst()
        //For public key bytes will be divide into 2
        let pointSize = privateKeyBytes.count / 3
        let xBytes = privateKeyBytes[0..<pointSize]
        publicKey.append(contentsOf: xBytes)
        let yBytes = privateKeyBytes[pointSize..<pointSize*2]
        publicKey.append(contentsOf: yBytes)
        print(publicKey)
        //dBytes wont be there in public key
        let dBytes = privateKeyBytes[pointSize*2..<pointSize*3]
        privateKey.append(contentsOf: dBytes)
        // this x, y and d bytes can be expressed in HexaDecimal format or base64 format
        print(dBytes)
//        LSILock.privatekeys = Array(privateKey[0..<min(16,privateKey.count)])
        LSILock.privtKey = privateKeySec

        guard let lock = LockSmartAPI.sharedInstance.getLock(lock_sn) else{return}
        lock.keyExchange(publicKey)

    }
Sourav Mishra
  • 501
  • 4
  • 21
  • What is the precise format of the data, and how did you generate it? Have you ensured that the format matches the format explained in the docs for SecKeyCopyExternalRepresentation? What is the error that is returned? – Rob Napier Feb 03 '20 at 14:26
  • @RobNapier thanks for response. Actually i'm working on lock using BLe. To prevent MITM we use ECDH, AES_CTR 128 bit encryption. The data (i.e.public key) which i want to convert in Seckey is get from lock after writing public key from my side. I have to use that key and my public key to generate shared secure key. Actually i don't know the format and also i didn't get any good documentation for it. Below are the error message i'm getting `SecKey` object creation for RSA failing, Error Domain Code=-50 "RSA private key creation from data failed – Sourav Mishra Feb 03 '20 at 17:20
  • @RobNapier i get the hex from the lock than i convert that hex to byte or data. i'm not aware about the SecKeyCopyExternalRepresentation format. – Sourav Mishra Feb 03 '20 at 17:36
  • I don't know precisely what you mean by "i convert that hex to byte or data." That can mean a lot of things, some correct, some incorrect. Without seeing some of the actual data in a reproducible case, it's difficult to debug this further. Almost certainly your data is in the wrong format, or not what you think it is. If you can post actual input data, and the code that processes it in a reproducible way, then it is probably solvable. (If you can't post the data, I can do this on a consulting basis, but I think we'd need to see your data.) – Rob Napier Feb 03 '20 at 17:42
  • @RobNapier, I get the hex from the lock. so i converted that hex to data. after that form data i try to get the seckey public key. Hope this is help. – Sourav Mishra Feb 03 '20 at 17:45
  • Unfortunately that doesn't help at all. What precisely is the data that you pass? According to the error, you're not passing properly formatted data. Without looking at the data, I can't help you fix it. Just as importantly (but not sufficient to solve that), how do you "convert that hex to data?" There are several ways to do that, not all of which are correct. Since it's not working, you have to investigate every step of the process. – Rob Napier Feb 03 '20 at 20:44
  • @RobNapier i have updated my question. can you please check now. it might help to get some solution. – Sourav Mishra Feb 05 '20 at 05:26
  • The key you've posted here (starting 21…) isn't an EC key. It's the wrong length and the wrong format. I haven't figured out what it is yet, but it's very suspicious being exact 512-bits long and you passing 512 as the length. (512 isn't a number associated with EC keys; *521* is an appropriate value, but just changing this to 521 isn't the answer). The output of a 521-bit key should be about 133 bytes and start with an 04. A 256-bit key should be 65 bytes and also start with an 04. I would go back to the documentation on this lock and make sure it's an EC key. – Rob Napier Feb 05 '20 at 14:39
  • @RobNapier i apologize i'm too late. i solved my query. RobNapier you are correct. i was making a wrong for EC key. A 256-bit key should be 65 bytes and also start with an 04. Thanks a lot for help – Sourav Mishra Feb 15 '20 at 18:36

0 Answers0