ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
identity.h File Reference

Go to the source code of this file.

Functions

asciichat_error_t acds_identity_generate (uint8_t public_key[32], uint8_t secret_key[64])
 Generate new Ed25519 keypair.
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_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[(32 *2+1)])
 Compute SHA256 fingerprint of public key.
asciichat_error_t acds_identity_default_path (char *path_out, size_t path_size)
 Get default identity file path for current platform.

Function Documentation

◆ acds_identity_default_path()

asciichat_error_t acds_identity_default_path ( char * path_out,
size_t path_size )

Get default identity file path for current platform.

Parameters
path_outOutput buffer for path (should be at least 256 bytes)
path_sizeSize of output buffer
Returns
ASCIICHAT_OK on success, error code otherwise

Returns:

  • Unix: ~/.config/ascii-chat/acds_identity
  • Windows: APPDATA%\ascii-chat\acds_identity

Definition at line 155 of file identity.c.

155 {
156 if (!path_out || path_size == 0) {
157 return SET_ERRNO(ERROR_INVALID_PARAM, "path_out cannot be NULL and path_size must be > 0");
158 }
159
160 // Get platform-specific config directory (~/.config/ascii-chat/ or %APPDATA%\ascii-chat\‍)
161 char *config_dir = platform_get_config_dir();
162 if (!config_dir) {
163 return SET_ERRNO(ERROR_CONFIG, "Failed to get config directory");
164 }
165
166 // Append "acds_identity" to config directory
167 int written = safe_snprintf(path_out, path_size, "%sacds_identity", config_dir);
168 SAFE_FREE(config_dir);
169
170 if (written < 0 || (size_t)written >= path_size) {
171 return SET_ERRNO(ERROR_CONFIG, "Path buffer too small");
172 }
173
174 return ASCIICHAT_OK;
175}
#define SET_ERRNO(code,...)
#define SAFE_FREE(ptr)
Definition common.h:377
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_CONFIG
Definition error_codes.h:52
@ ERROR_INVALID_PARAM
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Platform-safe snprintf wrapper.

References ASCIICHAT_OK, ERROR_CONFIG, ERROR_INVALID_PARAM, SAFE_FREE, safe_snprintf(), and SET_ERRNO.

Referenced by discovery_session_create().

◆ acds_identity_fingerprint()

void acds_identity_fingerprint ( const uint8_t public_key[32],
char fingerprint[(32 *2+1)] )

Compute SHA256 fingerprint of public key.

Parameters
public_key32-byte Ed25519 public key
fingerprintOutput buffer for 65 bytes (64 hex chars + null terminator)

Definition at line 134 of file identity.c.

135 {
136 if (!public_key || !fingerprint) {
137 log_error("NULL parameters");
138 return;
139 }
140
141 // Compute SHA256 hash of public key
142 uint8_t hash[crypto_hash_sha256_BYTES];
143 if (key_fingerprint_digest(public_key, hash) != ASCIICHAT_OK) {
144 fingerprint[0] = '\0';
145 return;
146 }
147
148 // Convert to hex string
149 for (int i = 0; i < 32; i++) {
150 safe_snprintf(&fingerprint[i * 2], 3, "%02x", hash[i]);
151 }
152 fingerprint[64] = '\0';
153}
unsigned char uint8_t
Definition common.h:60
#define log_error(...)
Log an ERROR message.
Definition log/log.h:634
asciichat_error_t key_fingerprint_digest(const uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], uint8_t digest[KEYMASK_DIGEST_SIZE])
Definition keymask.c:11

References ASCIICHAT_OK, ED25519_PUBLIC_KEY_SIZE, HEX_STRING_SIZE_32, key_fingerprint_digest(), log_error, and safe_snprintf().

Referenced by discovery_session_create().

◆ acds_identity_generate()

asciichat_error_t acds_identity_generate ( uint8_t public_key[32],
uint8_t secret_key[64] )

Generate new Ed25519 keypair.

Parameters
public_keyOutput buffer for 32-byte public key
secret_keyOutput buffer for 64-byte secret key
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 22 of file identity.c.

23 {
24 if (!public_key || !secret_key) {
25 return SET_ERRNO(ERROR_INVALID_PARAM, "public_key and secret_key cannot be NULL");
26 }
27
28 // Generate Ed25519 keypair using libsodium
29 if (crypto_sign_keypair(public_key, secret_key) != 0) {
30 return SET_ERRNO(ERROR_CRYPTO, "Failed to generate Ed25519 keypair");
31 }
32
33 log_debug("Generated new Ed25519 identity keypair");
34 return ASCIICHAT_OK;
35}
@ ERROR_CRYPTO
Definition error_codes.h:93
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595

References ASCIICHAT_OK, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ERROR_CRYPTO, ERROR_INVALID_PARAM, log_debug, and SET_ERRNO.

Referenced by discovery_session_create().

◆ acds_identity_load()

asciichat_error_t acds_identity_load ( const char * path,
uint8_t public_key[32],
uint8_t secret_key[64] )

Load identity from file.

Parameters
pathPath to identity file (e.g., ~/.config/ascii-chat/acds_identity)
public_keyOutput buffer for 32-byte public key
secret_keyOutput buffer for 64-byte secret key
Returns
ASCIICHAT_OK on success, ERROR_CONFIG if file doesn't exist

Definition at line 37 of file identity.c.

38 {
39 if (!path || !public_key || !secret_key) {
40 return SET_ERRNO(ERROR_INVALID_PARAM, "path, public_key, and secret_key cannot be NULL");
41 }
42
43 // Open file for reading
44 FILE *fp = platform_fopen("file_stream", path, "rb");
45 if (!fp) {
46 if (errno == ENOENT) {
47 return SET_ERRNO(ERROR_CONFIG, "Identity file does not exist: %s", path);
48 }
49 return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to open identity file: %s", path);
50 }
51
52 // Preserve the original raw libsodium identity format while accepting the
53 // OpenSSH Ed25519 private keys used by the rest of ascii-chat.
54 uint8_t raw_secret[crypto_sign_SECRETKEYBYTES];
55 const size_t raw_bytes = fread(raw_secret, 1, sizeof(raw_secret), fp);
56 const int trailing_byte = fgetc(fp);
57 fclose(fp);
58 if (raw_bytes == sizeof(raw_secret) && trailing_byte == EOF) {
59 uint8_t derived_public[crypto_sign_PUBLICKEYBYTES];
60 if (crypto_sign_ed25519_sk_to_pk(derived_public, raw_secret) != 0) {
61 sodium_memzero(raw_secret, sizeof(raw_secret));
62 return SET_ERRNO(ERROR_CONFIG, "Identity file contains an invalid Ed25519 secret key: %s", path);
63 }
64 memcpy(secret_key, raw_secret, sizeof(raw_secret));
65 memcpy(public_key, derived_public, sizeof(derived_public));
66 sodium_memzero(raw_secret, sizeof(raw_secret));
67 log_info("Loaded raw Ed25519 identity from %s", path);
68 return ASCIICHAT_OK;
69 }
70 sodium_memzero(raw_secret, sizeof(raw_secret));
71
72 private_key_t parsed_key = {0};
73 asciichat_error_t parse_result = parse_ssh_private_key(path, &parsed_key);
74 if (parse_result != ASCIICHAT_OK) {
75 sodium_memzero(&parsed_key, sizeof(parsed_key));
76 return parse_result;
77 }
78 if (parsed_key.type != KEY_TYPE_ED25519) {
79 sodium_memzero(&parsed_key, sizeof(parsed_key));
80 return SET_ERRNO(ERROR_CONFIG, "Discovery identity key must be Ed25519: %s", path);
81 }
82
83 memcpy(secret_key, parsed_key.key.ed25519, crypto_sign_SECRETKEYBYTES);
84 memcpy(public_key, parsed_key.public_key, crypto_sign_PUBLICKEYBYTES);
85 sodium_memzero(&parsed_key, sizeof(parsed_key));
86 log_info("Loaded OpenSSH Ed25519 identity from %s", path);
87 return ASCIICHAT_OK;
88}
#define SET_ERRNO_SYS(code,...)
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
uint8_t ed25519[ED25519_PRIVATE_KEY_SIZE]
Definition key_types.h:100
key_type_t type
Definition key_types.h:98
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]
Definition key_types.h:105
asciichat_error_t parse_ssh_private_key(const char *key_path, private_key_t *key_out)
Parse SSH Ed25519 private key from file.
Definition ssh_keys.c:984
union private_key_t::@040247167361101132173265304166142033301213115260 key
@ KEY_TYPE_ED25519
Definition key_types.h:54
#define log_info(...)
Log an INFO message.
Definition log/log.h:608
int errno
Private identity-key material used for server authentication and signing.
Definition key_types.h:97

References ASCIICHAT_OK, private_key_t::ed25519, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, errno, ERROR_CONFIG, ERROR_INVALID_PARAM, private_key_t::key, KEY_TYPE_ED25519, log_info, parse_ssh_private_key(), private_key_t::public_key, SET_ERRNO, SET_ERRNO_SYS, and private_key_t::type.

Referenced by discovery_session_create().

◆ acds_identity_save()

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.

Parameters
pathPath to identity file
public_key32-byte public key
secret_key64-byte secret key
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 90 of file identity.c.

91 {
92 if (!path || !public_key || !secret_key) {
93 return SET_ERRNO(ERROR_INVALID_PARAM, "path, public_key, and secret_key cannot be NULL");
94 }
95
96 // Extract directory path and create all parent directories
97 char dir_path[PLATFORM_MAX_PATH_LENGTH];
98 SAFE_STRNCPY(dir_path, path, sizeof(dir_path));
99
100 // Find last directory separator
101 char *last_sep = strrchr(dir_path, '/');
102 if (!last_sep) {
103 last_sep = strrchr(dir_path, '\\');
104 }
105
106 if (last_sep) {
107 *last_sep = '\0';
108
109 // Create directory recursively (mkdir -p equivalent)
110 asciichat_error_t result = platform_mkdir_recursive(dir_path, 0700);
111 if (result != ASCIICHAT_OK) {
112 return result;
113 }
114 }
115
116 // Open file for writing (mode 0600 = owner read/write only)
117 int fd = platform_open("identity_file", path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
118 if (fd < 0) {
119 return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to create identity file: %s", path);
120 }
121
122 // Write secret key (64 bytes)
123 ssize_t written = write(fd, secret_key, 64);
124 close(fd);
125
126 if (written != 64) {
127 return SET_ERRNO(ERROR_CONFIG, "Failed to write identity file (wrote %zd/64 bytes): %s", written, path);
128 }
129
130 log_info("Saved identity to %s", path);
131 return ASCIICHAT_OK;
132}
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:423
#define PLATFORM_MAX_PATH_LENGTH
Definition common.h:95

References ASCIICHAT_OK, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ERROR_CONFIG, ERROR_INVALID_PARAM, log_info, PLATFORM_MAX_PATH_LENGTH, SAFE_STRNCPY, SET_ERRNO, and SET_ERRNO_SYS.

Referenced by discovery_session_create().