News
Creating a macOS KeyChain entry in C
by admin on Jan.05, 2025, under News
The following example shows how we can create a macOS KeyChain entry to store and retrieve secrets.
// clang keychain.c -o keychain -framework Security -framework CoreFoundation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Security/Security.h>
// Function to store a password in the keychain
void store_password(const char *service, const char *account, const char *password) {
CFStringRef serviceRef = CFStringCreateWithCString(NULL, service, kCFStringEncodingUTF8);
CFStringRef accountRef = CFStringCreateWithCString(NULL, account, kCFStringEncodingUTF8);
CFStringRef passwordRef = CFStringCreateWithCString(NULL, password, kCFStringEncodingUTF8);
CFDictionaryRef attributes = CFDictionaryCreate(NULL,
(const void *[]){ kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData },
(const void *[]){ kSecClassGenericPassword, serviceRef, accountRef, CFDataCreate(NULL, (const UInt8 *)password, strlen(password)) },
4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
OSStatus status = SecItemAdd(attributes, NULL);
if (status == errSecSuccess) {
printf("Password stored successfully.\n");
} else if (status == errSecDuplicateItem) {
printf("Password for this service and account already exists. Updating...\n");
CFDictionaryRef query = CFDictionaryCreate(NULL,
(const void *[]){ kSecClass, kSecAttrService, kSecAttrAccount },
(const void *[]){ kSecClassGenericPassword, serviceRef, accountRef },
3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryRef updateAttributes = CFDictionaryCreate(NULL,
(const void *[]){ kSecValueData },
(const void *[]){ CFDataCreate(NULL, (const UInt8 *)password, strlen(password)) },
1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
status = SecItemUpdate(query, updateAttributes);
if (status == errSecSuccess) {
printf("Password updated successfully.\n");
} else {
fprintf(stderr, "Failed to update password. Error code: %d\n", (int)status);
}
CFRelease(query);
CFRelease(updateAttributes);
} else {
fprintf(stderr, "Failed to store password. Error code: %d\n", (int)status);
}
CFRelease(attributes);
CFRelease(serviceRef);
CFRelease(accountRef);
CFRelease(passwordRef);
}
// Function to retrieve a password from the keychain
void retrieve_password(const char *service, const char *account) {
CFStringRef serviceRef = CFStringCreateWithCString(NULL, service, kCFStringEncodingUTF8);
CFStringRef accountRef = CFStringCreateWithCString(NULL, account, kCFStringEncodingUTF8);
CFDictionaryRef query = CFDictionaryCreate(NULL,
(const void *[]){ kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData },
(const void *[]){ kSecClassGenericPassword, serviceRef, accountRef, kCFBooleanTrue },
4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching(query, &result);
if (status == errSecSuccess) {
CFDataRef passwordData = (CFDataRef)result;
printf("Password retrieved: %.*s\n", (int)CFDataGetLength(passwordData), CFDataGetBytePtr(passwordData));
CFRelease(passwordData);
} else if (status == errSecItemNotFound) {
printf("Password not found for service: %s and account: %s\n", service, account);
} else {
fprintf(stderr, "Failed to retrieve password. Error code: %d\n", (int)status);
}
CFRelease(query);
CFRelease(serviceRef);
CFRelease(accountRef);
}
int main() {
const char *service = "example.com";
const char *account = "user@example.com";
const char *password = "mypassword123";
// Store the password in the Keychain
store_password(service, account, password);
// Retrieve the password from the Keychain
retrieve_password(service, account);
return 0;
}
We may compile it using clang:
clang keychain.c -o keychain -framework Security -framework CoreFoundation




