@noloader напомнил мне, что я могу посмотреть в ssh-keygen.c.
Вот что я нашел.
Это вызывается для всех типов ключей (rsa, dsa, ecdsa):
key_to_blob(key, &blob, &len);
uu = xmalloc(2*len);
n = uuencode(blob, len, uu, 2*len);
if (n > 0) {
fprintf(f, "%s %s", key_ssh_name(key), uu);
success = 1;
}
Где key_to_blob() в конечном итоге приводит к to_blob():
to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
{
Buffer b;
int len, type;
if (blobp != NULL)
*blobp = NULL;
if (lenp != NULL)
*lenp = 0;
if (key == NULL) {
error("key_to_blob: key == NULL");
return 0;
}
buffer_init(&b);
type = force_plain ? key_type_plain(key->type) : key->type;
switch (type) {
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
case KEY_ED25519_CERT:
/* Use the existing blob */
buffer_append(&b, buffer_ptr(&key->cert->certblob),
buffer_len(&key->cert->certblob));
Что в итоге приводит к этому:
buffer_clear(&k->cert->certblob);
buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
/* -v01 certs put nonce first */
arc4random_buf(&nonce, sizeof(nonce));
if (!key_cert_is_legacy(k))
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
/* XXX this substantially duplicates to_blob(); refactor */
switch (k->type) {
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
buffer_put_cstring(&k->cert->certblob,
key_curve_nid_to_name(k->ecdsa_nid));
buffer_put_ecpoint(&k->cert->certblob,
EC_KEY_get0_group(k->ecdsa),
EC_KEY_get0_public_key(k->ecdsa));
break;
#endif
Что в конечном итоге приводит к этому (2):
int
buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
const EC_POINT *point)
{
u_char *buf = NULL;
size_t len;
BN_CTX *bnctx;
int ret = -1;
/* Determine length */
if ((bnctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new failed", __func__);
len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
NULL, 0, bnctx);
if (len > BUFFER_MAX_ECPOINT_LEN) {
error("%s: giant EC point: len = %lu (max %u)",
__func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
goto out;
}
/* Convert */
buf = xmalloc(len);
if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
buf, len, bnctx) != len) {
error("%s: EC_POINT_point2oct length mismatch", __func__);
goto out;
}
/* Append */
buffer_put_string(buffer, buf, len);
ret = 0;
out:
if (buf != NULL) {
bzero(buf, len);
free(buf);
}
BN_CTX_free(bnctx);
return ret;
}
Здесь строится фактическая строка:
buf = xmalloc(len);
if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
buf, len, bnctx) != len) {
error("%s: EC_POINT_point2oct length mismatch", __func__);
goto out;
}
/* Append */
buffer_put_string(buffer, buf, len);
Где для отображения «строки октетов» используется следующее (bnctx должно иметь значение NULL):
EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, buf, len, bnctx);
person
Dustin Oprea
schedule
21.02.2014