ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
identity.c
Go to the documentation of this file.
1
11#include <sodium.h>
12#include <stdio.h>
13#include <string.h>
14#include <errno.h>
15#include <sys/stat.h>
16
18 if (!public_key || !secret_key) {
19 return SET_ERRNO(ERROR_INVALID_PARAM, "public_key and secret_key cannot be NULL");
20 }
21
22 // Generate Ed25519 keypair using libsodium
23 if (crypto_sign_keypair(public_key, secret_key) != 0) {
24 return SET_ERRNO(ERROR_CRYPTO, "Failed to generate Ed25519 keypair");
25 }
26
27 log_debug("Generated new Ed25519 identity keypair");
28 return ASCIICHAT_OK;
29}
30
31asciichat_error_t acds_identity_load(const char *path, uint8_t public_key[32], uint8_t secret_key[64]) {
32 if (!path || !public_key || !secret_key) {
33 return SET_ERRNO(ERROR_INVALID_PARAM, "path, public_key, and secret_key cannot be NULL");
34 }
35
36 // Open file for reading
37 FILE *fp = platform_fopen("file_stream", path, "rb");
38 if (!fp) {
39 if (errno == ENOENT) {
40 return SET_ERRNO(ERROR_CONFIG, "Identity file does not exist: %s", path);
41 }
42 return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to open identity file: %s", path);
43 }
44
45 // Read secret key (64 bytes)
46 size_t read = fread(secret_key, 1, 64, fp);
47 if (read != 64) {
48 fclose(fp);
49 return SET_ERRNO(ERROR_CONFIG, "Identity file corrupted (expected 64 bytes, got %zu): %s", read, path);
50 }
51
52 // Extract public key from secret key (last 32 bytes of Ed25519 secret key)
53 memcpy(public_key, secret_key + 32, 32);
54
55 fclose(fp);
56 log_info("Loaded identity from %s", path);
57 return ASCIICHAT_OK;
58}
59
60asciichat_error_t acds_identity_save(const char *path, const uint8_t public_key[32], const uint8_t secret_key[64]) {
61 if (!path || !public_key || !secret_key) {
62 return SET_ERRNO(ERROR_INVALID_PARAM, "path, public_key, and secret_key cannot be NULL");
63 }
64
65 // Extract directory path and create all parent directories
66 char dir_path[PLATFORM_MAX_PATH_LENGTH];
67 SAFE_STRNCPY(dir_path, path, sizeof(dir_path));
68
69 // Find last directory separator
70 char *last_sep = strrchr(dir_path, '/');
71 if (!last_sep) {
72 last_sep = strrchr(dir_path, '\\');
73 }
74
75 if (last_sep) {
76 *last_sep = '\0';
77
78 // Create directory recursively (mkdir -p equivalent)
79 asciichat_error_t result = platform_mkdir_recursive(dir_path, 0700);
80 if (result != ASCIICHAT_OK) {
81 return result;
82 }
83 }
84
85 // Open file for writing (mode 0600 = owner read/write only)
86 int fd = platform_open("identity_file", path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
87 if (fd < 0) {
88 return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to create identity file: %s", path);
89 }
90
91 // Write secret key (64 bytes)
92 ssize_t written = write(fd, secret_key, 64);
93 close(fd);
94
95 if (written != 64) {
96 return SET_ERRNO(ERROR_CONFIG, "Failed to write identity file (wrote %zd/64 bytes): %s", written, path);
97 }
98
99 log_info("Saved identity to %s", path);
100 return ASCIICHAT_OK;
101}
102
103void acds_identity_fingerprint(const uint8_t public_key[32], char fingerprint[65]) {
104 if (!public_key || !fingerprint) {
105 log_error("acds_identity_fingerprint: NULL parameters");
106 return;
107 }
108
109 // Compute SHA256 hash of public key
110 uint8_t hash[32];
111 crypto_hash_sha256(hash, public_key, 32);
112
113 // Convert to hex string
114 for (int i = 0; i < 32; i++) {
115 safe_snprintf(&fingerprint[i * 2], 3, "%02x", hash[i]);
116 }
117 fingerprint[64] = '\0';
118}
119
120asciichat_error_t acds_identity_default_path(char *path_out, size_t path_size) {
121 if (!path_out || path_size == 0) {
122 return SET_ERRNO(ERROR_INVALID_PARAM, "path_out cannot be NULL and path_size must be > 0");
123 }
124
125 // Get platform-specific config directory (~/.config/ascii-chat/ or %APPDATA%\ascii-chat\‍)
126 char *config_dir = platform_get_config_dir();
127 if (!config_dir) {
128 return SET_ERRNO(ERROR_CONFIG, "Failed to get config directory");
129 }
130
131 // Append "acds_identity" to config directory
132 int written = safe_snprintf(path_out, path_size, "%sacds_identity", config_dir);
133 SAFE_FREE(config_dir);
134
135 if (written < 0 || (size_t)written >= path_size) {
136 return SET_ERRNO(ERROR_CONFIG, "Path buffer too small");
137 }
138
139 return ASCIICHAT_OK;
140}
Platform abstraction layer umbrella header providing unified cross-platform API.
Cross-platform error handling utilities.
Cross-platform filesystem operations.
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:414
#define SAFE_FREE(ptr)
Definition common.h:376
unsigned char uint8_t
Definition common.h:56
#define SET_ERRNO_SYS(code, context_msg,...)
Set error code with custom message and system error context, returning the error code.
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_CONFIG
Definition error_codes.h:57
@ ERROR_CRYPTO
Definition error_codes.h:96
@ ERROR_INVALID_PARAM
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:148
asciichat_error_t platform_mkdir_recursive(const char *path, int mode)
Create directories recursively (mkdir -p equivalent)
int platform_open(const char *name, const char *pathname, int flags,...)
Safe file open (open replacement)
FILE * platform_fopen(const char *name, const char *filename, const char *mode)
Safe file open stream (fopen replacement)
int errno
char * platform_get_config_dir(void)
Get the application configuration directory.
Definition util.c:104
asciichat_error_t acds_identity_load(const char *path, uint8_t public_key[32], uint8_t secret_key[64])
Load identity from file.
Definition identity.c:31
asciichat_error_t acds_identity_default_path(char *path_out, size_t path_size)
Get default identity file path for current platform.
Definition identity.c:120
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.
Definition identity.c:60
void acds_identity_fingerprint(const uint8_t public_key[32], char fingerprint[65])
Compute SHA256 fingerprint of public key.
Definition identity.c:103
asciichat_error_t acds_identity_generate(uint8_t public_key[32], uint8_t secret_key[64])
Generate new Ed25519 keypair.
Definition identity.c:17
📝 Logging API with multiple log levels and terminal output control
#define PLATFORM_MAX_PATH_LENGTH
Definition system.c:69