encode.c (1910B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include "common.h" 6 #include "armor.h" 7 #include "b64.h" 8 9 #ifdef __cplusplus 10 extern "C" { 11 #endif 12 13 // Wrap raw bytes in an ascii-armor block; returns malloc'd NUL-terminated text. 14 static char *asc_wrap(const char *label, const unsigned char *raw, size_t rawlen, 15 size_t *outlen) { 16 char *b64, *out; 17 size_t b64len, need; 18 int n; 19 20 b64 = asc_b64_encode(raw, rawlen, &b64len); 21 if (!b64) return NULL; 22 // "-----BEGIN %s-----\n" + b64 + "-----END %s-----\n" + NUL 23 need = strlen("-----BEGIN -----\n-----END -----\n") + 2 * strlen(label) + b64len + 1; 24 out = malloc(need); 25 if (!out) { 26 free(b64); 27 return NULL; 28 } 29 n = snprintf(out, need, "-----BEGIN %s-----\n%s-----END %s-----\n", 30 label, b64, label); 31 free(b64); 32 if (n < 0 || (size_t)n >= need) { 33 free(out); 34 return NULL; 35 } 36 *outlen = (size_t)n; 37 return out; 38 } 39 40 char * fmt_asc_encode(struct KeyPair *kp, size_t *len) { 41 char *priv = NULL, *pub = NULL, *out; 42 size_t privlen = 0, publen = 0; 43 44 if (!kp || !kp->public_key || !len) return NULL; 45 // Armor carries just the key bytes, no prefix. A full pair emits both a 46 // PRIVATE block (64 private bytes) and a PUBLIC block (32 public bytes); 47 // a pub-only pair emits just the PUBLIC block. 48 if (kp->private_key) { 49 priv = asc_wrap(ASC_LABEL_PRIVATE, kp->private_key, 64, &privlen); 50 if (!priv) return NULL; 51 } 52 pub = asc_wrap(ASC_LABEL_PUBLIC, kp->public_key, 32, &publen); 53 if (!pub) { 54 if (priv) free(priv); 55 return NULL; 56 } 57 out = malloc(privlen + publen + 1); 58 if (!out) { 59 if (priv) free(priv); 60 if (pub) free(pub); 61 return NULL; 62 } 63 memcpy(out, priv, privlen); 64 memcpy(out + privlen, pub, publen); 65 out[privlen + publen] = '\0'; 66 free(priv); 67 free(pub); 68 *len = privlen + publen; 69 return out; 70 } 71 72 #ifdef __cplusplus 73 } // extern "C" 74 #endif