22 if (!public_key || !secret_key) {
27 if (crypto_sign_keypair(public_key, secret_key) != 0) {
31 log_debug(
"Generated new Ed25519 identity keypair");
36 if (!path || !public_key || !secret_key) {
41 FILE *fp = fopen(path,
"rb");
43 if (
errno == ENOENT) {
50 size_t read = fread(secret_key, 1, 64, fp);
53 return SET_ERRNO(
ERROR_CONFIG,
"Identity file corrupted (expected 64 bytes, got %zu): %s", read, path);
57 memcpy(public_key, secret_key + 32, 32);
60 log_info(
"Loaded identity from %s", path);
73 if (!path || path[0] ==
'\0') {
90 for (
char *p = tmp + 1; *p; p++) {
91 if (*p == sep || *p ==
'/' || *p ==
'\\') {
96 if (tmp[0] !=
'\0' && strcmp(tmp,
".") != 0) {
99 if (_mkdir(tmp) != 0 &&
errno != EEXIST) {
101 if (
errno != ENOENT) {
102 log_debug(
"Failed to create directory: %s (errno=%d)", tmp,
errno);
107 if (mkdir(tmp, 0700) != 0 &&
errno != EEXIST) {
109 if (
errno != ENOENT) {
110 log_debug(
"Failed to create directory: %s (errno=%d)", tmp,
errno);
122 if (_mkdir(tmp) != 0 &&
errno != EEXIST) {
123 if (
errno != ENOENT) {
128 if (mkdir(tmp, 0700) != 0 &&
errno != EEXIST) {
129 if (
errno != ENOENT) {
139 if (!path || !public_key || !secret_key) {
148 char *last_sep = strrchr(dir_path,
'/');
150 last_sep = strrchr(dir_path,
'\\');
164 int fd =
platform_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
170 ssize_t written = write(fd, secret_key, 64);
174 return SET_ERRNO(
ERROR_CONFIG,
"Failed to write identity file (wrote %zd/64 bytes): %s", written, path);
177 log_info(
"Saved identity to %s", path);
182 if (!public_key || !fingerprint) {
183 log_error(
"acds_identity_fingerprint: NULL parameters");
189 crypto_hash_sha256(hash, public_key, 32);
192 for (
int i = 0; i < 32; i++) {
193 sprintf(&fingerprint[i * 2],
"%02x", hash[i]);
195 fingerprint[64] =
'\0';
199 if (!path_out || path_size == 0) {
210 int written = snprintf(path_out, path_size,
"%s\\ascii-chat\\acds_identity", appdata);
211 if (written < 0 || (
size_t)written >= path_size) {
222 const char *xdg_config =
SAFE_GETENV(
"XDG_CONFIG_HOME");
223 if (xdg_config && xdg_config[0] !=
'\0') {
224 int written = snprintf(path_out, path_size,
"%s/ascii-chat/acds_identity", xdg_config);
225 if (written < 0 || (
size_t)written >= path_size) {
229 int written = snprintf(path_out, path_size,
"%s/.config/ascii-chat/acds_identity", home);
230 if (written < 0 || (
size_t)written >= path_size) {
🔌 Cross-platform abstraction layer umbrella header for ascii-chat
Cross-platform file system operations.
#define SAFE_STRNCPY(dst, src, size)
#define SAFE_GETENV(name)
#define SET_ERRNO_SYS(code, context_msg,...)
Set error code with custom message and system error context.
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
asciichat_error_t
Error and exit codes - unified status values (0-255)
#define log_error(...)
Log an ERROR message.
#define log_info(...)
Log an INFO message.
#define log_debug(...)
Log a DEBUG message.
asciichat_error_t acds_identity_load(const char *path, uint8_t public_key[32], uint8_t secret_key[64])
Load identity from file.
asciichat_error_t acds_identity_default_path(char *path_out, size_t path_size)
Get default identity file path for current platform.
asciichat_error_t acds_identity_save(const char *path, const uint8_t public_key[32], const uint8_t secret_key[64])
Save identity to file.
void acds_identity_fingerprint(const uint8_t public_key[32], char fingerprint[65])
Compute SHA256 fingerprint of public key.
asciichat_error_t acds_identity_generate(uint8_t public_key[32], uint8_t secret_key[64])
Generate new Ed25519 keypair.
Identity key management for discovery server.
📝 Logging API with multiple log levels and terminal output control