Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SecKey::generate(...) => CFError #205

Open
HS3003991 opened this issue May 12, 2024 · 5 comments
Open

SecKey::generate(...) => CFError #205

HS3003991 opened this issue May 12, 2024 · 5 comments

Comments

@HS3003991
Copy link

Hello,

I'm attempting to generate a KeyPair using the "SecKey::generate()" method. However, upon building and running the code, the OS throws the following error:

"CFError { domain: "NSOSStatusErrorDomain", code: -34018, description: "The operation couldn’t be completed. (OSStatus error -34018 - failed to generate asymmetric keypair)" }"

Has anyone encountered the same error and managed to resolve it?

Best regards,
Daniel

@toksdotdev
Copy link
Collaborator

toksdotdev commented May 18, 2024

Can you confirm that you're providing a key size?

To generate a key pair, you need to specify at least the kSecAttrKeyType and kSecAttrKeySizeInBits (see docs for reference).

Here is a code sample:

let key_type_attr = unsafe { CFString::wrap_under_get_rule(kSecAttrKeyType) };
let rsa_key_type = unsafe { CFString::wrap_under_get_rule(kSecAttrKeyTypeRSA) };
let key_size_attr = unsafe { CFString::wrap_under_get_rule(kSecAttrKeySizeInBits) };

let attributes = CFDictionary::from_CFType_pairs(&[
    (key_type_attr.as_CFType(), rsa_key_type.as_CFType()),
    (key_size_attr.as_CFType(), CFNumber::from(2048).as_CFType()),
]);

let generated = SecKey::generate(attributes.to_untyped());

@zemse
Copy link

zemse commented Jun 5, 2024

The following code worked for me.

use security_framework::key::{Algorithm, GenerateKeyOptions, KeyType, SecKey, Token};

fn main() {
    let options = GenerateKeyOptions {
        key_type: Some(KeyType::ec()),
        size_in_bits: None,
        label: Some("com.example.mykey".to_string()),
        token: Some(Token::SecureEnclave),
        location: None,
        access_control: None,
    };
    let key = SecKey::generate(options.to_dictionary()).unwrap();
    let signature = key
        .create_signature(
            Algorithm::ECDSASignatureMessageX962SHA256,
            vec![0; 32].as_slice(),
        )
        .unwrap();
    println!("signature: {:?}", signature);
}

However, this generates a new key every time even if the label is the same. I am still figuring out how I can get the same key again.

@HS3003991
Copy link
Author

Thank you very much for help. It was not a a problem with the code. At least it was something with the entitlements...

But thank you very much!

@zemse
Copy link

zemse commented Jun 11, 2024

At least it was something with the entitlements..

Can you please share your solution?

When I set the location I get the exact error you have mentioned above. It seems I am not able to set the location.

let options = GenerateKeyOptions {
  ...
  location: Some(Location::DataProtectionKeychain),
  ...
};

Edit: based on this comment, it seems that the binary has to be authenticated in order for this to work, and we need to purchase the apple developer program.

@HS3003991
Copy link
Author

HS3003991 commented Jun 12, 2024

Yes of course. In my Case I had to Codesign the Rust generated executable. When you are developing (for example) with Xcode + Swift, the codesigning happens automatically, when you have a valid Developer Account, Developer Certificate and Profile.
When you are Programming with Rust and have a Executable to run, so you have Codesign the Executable manually and add an .entitlements File to the executable.
I did this with the following Command:
codesign -f -s "[Identifier / hash of the Apple Developer Certificate]" --entitlements "[Path to the Entitlement file]" -o runtime -i "[Bundle identifier]" "[Path to the executable / Mach-O file]"

And my Entitlement-File looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>com.apple.application-identifier</key>
        <string>**[Paste your App / Bundle Identifier]**</string>
        <key>com.apple.developer.team-identifier</key>
        <string>**[Paste DeveloperTeam-ID]**</string>
        <key>com.apple.security.app-sandbox</key>
        <false/>
        <key>com.apple.security.files.user-selected.read-only</key>
        <true/>
        <key>com.apple.security.get-task-allow</key>
        <true/>
        <key>keychain-access-groups</key>
        <array>
                <string>[Paste your KeyChain-Access-Group]</string>
        </array>
</dict>
</plist>

I hope I could help you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants