5#include <mbedtls/sha1.h>
6#include <mbedtls/sha256.h>
14static const uint8_t kOidEd25519[] = {0x09, 0x2B, 0x06, 0x01, 0x04, 0x01,
15 0xDA, 0x47, 0x0F, 0x01};
16static const uint8_t kOidP256[] = {0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
21size_t buildPublicKeyBody(uint8_t
curve,
22 const uint8_t* pubkey,
size_t pubkey_len,
24 uint8_t* out,
size_t out_size)
26 if (!out || !pubkey)
return 0;
31 if (!is_ed25519 && pubkey_len < 64)
return 0;
34 const uint8_t* oid = is_ed25519 ? kOidEd25519 : kOidP256;
35 const size_t oid_len = is_ed25519 ?
sizeof(kOidEd25519) : sizeof(kOidP256);
41 uint16_t bits = (pubkey[0] & 0x80) ? 256 : 255;
42 mpi[0] =
static_cast<uint8_t
>((bits >> 8) & 0xFF);
43 mpi[1] =
static_cast<uint8_t
>(bits & 0xFF);
49 mpi[0] =
static_cast<uint8_t
>((bits >> 8) & 0xFF);
50 mpi[1] =
static_cast<uint8_t
>(bits & 0xFF);
56 const size_t total = 1 + 4 + 1 + oid_len + mpi_len;
57 if (total > out_size)
return 0;
61 out[off++] = (created_at >> 24) & 0xFF;
62 out[off++] = (created_at >> 16) & 0xFF;
63 out[off++] = (created_at >> 8) & 0xFF;
64 out[off++] = created_at & 0xFF;
66 std::memcpy(out + off, oid, oid_len);
68 std::memcpy(out + off, mpi, mpi_len);
76 const uint8_t* pubkey,
size_t pubkey_len,
80 if (!out_fp)
return false;
83 const size_t body_len = buildPublicKeyBody(
curve, pubkey, pubkey_len,
84 created_at, body,
sizeof(body));
85 if (body_len == 0)
return false;
87 const uint8_t prefix[3] = {
89 static_cast<uint8_t
>((body_len >> 8) & 0xFF),
90 static_cast<uint8_t
>(body_len & 0xFF),
93 mbedtls_sha1_context ctx;
94 mbedtls_sha1_init(&ctx);
95 mbedtls_sha1_starts(&ctx);
96 mbedtls_sha1_update(&ctx, prefix,
sizeof(prefix));
97 mbedtls_sha1_update(&ctx, body, body_len);
98 mbedtls_sha1_finish(&ctx, out_fp);
99 mbedtls_sha1_free(&ctx);
104 const uint8_t* pubkey,
size_t pubkey_len,
108 if (!out_fp)
return false;
111 const size_t body_len = buildPublicKeyBody(
curve, pubkey, pubkey_len,
112 created_at, body,
sizeof(body));
113 if (body_len == 0)
return false;
116 const uint8_t prefix[5] = {
118 static_cast<uint8_t
>((body_len >> 24) & 0xFF),
119 static_cast<uint8_t
>((body_len >> 16) & 0xFF),
120 static_cast<uint8_t
>((body_len >> 8) & 0xFF),
121 static_cast<uint8_t
>(body_len & 0xFF),
124 mbedtls_sha256_context ctx;
125 mbedtls_sha256_init(&ctx);
126 mbedtls_sha256_starts(&ctx, 0);
127 mbedtls_sha256_update(&ctx, prefix,
sizeof(prefix));
128 mbedtls_sha256_update(&ctx, body, body_len);
129 mbedtls_sha256_finish(&ctx, out_fp);
130 mbedtls_sha256_free(&ctx);
136 uint8_t out_hash[32])
138 if (!fp_v4 || !
user_id || !out_hash)
return false;
140 uint8_t input[84] = {0};
141 std::memcpy(input, fp_v4, 20);
142 const size_t uid_len = std::strlen(
user_id);
143 std::memcpy(input + 20,
user_id, uid_len > 64 ? 64 : uid_len);
145 mbedtls_sha256(input,
sizeof(input), out_hash, 0);
#define ED25519_PUBKEY_SIZE
Ed25519 raw public key size in bytes.
#define MPI_FULL_SIZE_ED25519
Full Ed25519 MPI buffer size: 2 byte length prefix + 32 byte key.
#define OPENPGP_ALGO_ECDSA
Centralized magic-value constants for the OpenPGP smart-card application.
#define P256_PUBKEY_BITS
P-256 public key bit-length (used as MPI bit count).
#define MPI_HEADER_SIZE
OpenPGP MPI header size (2-byte length prefix).
#define OPENPGP_ALGO_EDDSA
OpenPGP algorithm ID for EdDSA (Ed25519).
#define MPI_FULL_SIZE_P256
Full P-256 MPI buffer size: 2 byte length prefix + 65 byte uncompressed key.
#define CDC_CURVE_ED25519
uint8_t user_id[FIDO2_USER_ID_MAX_LEN]
bool calculateFingerprintV4(uint8_t curve, const uint8_t *pubkey, size_t pubkey_len, uint32_t created_at, uint8_t out_fp[20])
Compute the RFC 4880 V4 OpenPGP fingerprint (SHA-1, 20 bytes).
bool gpgCrossSignDigest(const uint8_t fp_v4[20], const char *user_id, uint8_t out_hash[32])
Build the digest input for a cross-signature.
bool calculateFingerprintV5(uint8_t curve, const uint8_t *pubkey, size_t pubkey_len, uint32_t created_at, uint8_t out_fp[32])
Compute the V5 / RFC 9580 OpenPGP fingerprint (SHA-256, 32 bytes).