Voici une solution que j'ai trouvée en utilisant les bibliothèques OpenSSL. Je poste la question et la réponse sur le débordement de la pile dans l'espoir que cela épargnera aux autres le problème et le temps de la comprendre eux-mêmes.
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/bio.h>
int main(int argc, char * argv[])
{
struct stat sb;
unsigned char * buff;
int fd;
ssize_t len;
BIO * bio;
X509 * x;
unsigned err;
int pos;
char errmsg[1024];
const EVP_MD * digest;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int n;
// checks arguments
if (argc != 2)
{
fprintf(stderr, "Usage: peminfo <pemfile>\n");
return(1);
};
// checks file
if ((stat(argv[1], &sb)) == -1)
{
perror("peminfo: stat()");
return(1);
};
len = (sb.st_size * 2);
// allocates memory
if (!(buff = malloc(len)))
{
fprintf(stderr, "peminfo: out of virtual memory\n");
return(1);
};
// opens file for reading
if ((fd = open(argv[1], O_RDONLY)) == -1)
{
perror("peminfo: open()");
free(buff);
return(1);
};
// reads file
if ((len = read(fd, buff, len)) == -1)
{
perror("peminfo: read()");
free(buff);
return(1);
};
// closes file
close(fd);
// initialize OpenSSL
SSL_load_error_strings();
SSL_library_init();
// creates BIO buffer
bio = BIO_new_mem_buf(buff, len);
// decodes buffer
if (!(x = PEM_read_bio_X509(bio, NULL, 0L, NULL)))
{
while((err = ERR_get_error()))
{
errmsg[1023] = '\0';
ERR_error_string_n(err, errmsg, 1023);
fprintf(stderr, "peminfo: %s\n", errmsg);
};
BIO_free(bio);
free(buff);
return(1);
};
// prints x509 info
printf("name: %s\n", x->name);
printf("serial: ");
printf("%02X", x->cert_info->serialNumber->data[0]);
for(pos = 1; pos < x->cert_info->serialNumber->length; pos++)
printf(":%02X", x->cert_info->serialNumber->data[pos]);
printf("\n");
// calculate & print fingerprint
digest = EVP_get_digestbyname("sha1");
X509_digest(x, digest, md, &n);
printf("Fingerprint: ");
for(pos = 0; pos < 19; pos++)
printf("%02x:", md[pos]);
printf("%02x\n", md[19]);
// frees memory
BIO_free(bio);
free(buff);
return(0);
}
Voici la compilation et la sortie du programme ci-dessus:
$ cc -pedantic -W -Wall -Werror -O2 -Wno-deprecated -o peminfo peminfo.c \
> -lcrypto -lssl
$ ./peminfo /usr/local/etc/openldap/keys/ca-certs.pem
serial: 98:61:EB:C4:F2:C9:59:72
Fingerprint: 1d:59:d3:d4:4f:c9:e3:dc:f3:d7:66:b0:b8:7e:87:0b:01:73:c2:7e
Voici la sortie de l'utilitaire OpenSSL:
$ openssl x509 -noout -in /usr/local/etc/openldap/keys/ca-certs.pem \
> -fingerprint -serial
SHA1 Fingerprint=1D:59:D3:D4:4F:C9:E3:DC:F3:D7:66:B0:B8:7E:87:0B:01:73:C2:7E
serial=9861EBC4F2C95972