PEM_read_PUBKEY和PEM_read_RSA_PUBKEY两个函数都可以从PEM格式的文件中读取公钥,但它们处理公钥的方式不同。

  • PEM_read_PUBKEY函数读取的是一个包含任何类型公钥的PEM文件,这个文件通常以"-----BEGIN PUBLIC KEY-----"开始。这个函数返回一个EVP_PKEY结构,这是一个可以包含任何类型公钥的通用结构。
  • PEM_read_RSA_PUBKEY函数读取的是一个包含RSA公钥的PEM文件,这个文件通常以"-----BEGIN RSA PUBLIC KEY-----"开始。这个函数返回一个RSA结构,这是一个专门用于表示RSA公钥的结构。

因此,如果你有一个包含RSA公钥的PEM文件,你可以使用这两个函数中的任何一个来读取它,但是你得到的结果将是不同类型的结构。如果你使用PEM_read_PUBKEY函数,你将得到一个EVP_PKEY结构,你可以使用EVP_PKEY相关的函数来处理这个公钥。如果你使用PEM_read_RSA_PUBKEY函数,你将得到一个RSA结构,你可以使用RSA相关的函数来处理这个公钥。

此外,这两种类型的PEM格式的公钥在编码方式上也有所不同。"-----BEGIN PUBLIC KEY-----“格式的公钥使用的是X.509 SubjectPublicKeyInfo格式,而”-----BEGIN RSA PUBLIC KEY-----"格式的公钥使用的是PKCS#1 RSAPublicKey格式。这两种格式的主要区别在于,SubjectPublicKeyInfo格式包含了公钥的类型信息,而RSAPublicKey格式没有。

将X.509格式的公钥转换为PKCS#1 RSAPublicKey格式的PEM文件:
   openssl rsa -pubin -inform PEM -RSAPublicKey_out -in public_key.pem -out public_key_rsa.pem
将PKCS#1 RSAPublicKey格式的PEM文件转换为X.509 SubjectPublicKeyInfo格式的PEM文件
   openssl rsa -pubin -inform PEM -in public_key_rsa.pem -outform PEM -out public_key_x509.pem

EVP_PKEY和RSA都是OpenSSL库中的数据类型,它们都用于表示密钥,但它们的用途和功能有所不同。

  • RSA:这是一个专门用于表示RSA密钥的数据类型。它包含了RSA密钥的所有组成部分(例如,公钥和私钥的模数和指数)。你可以使用OpenSSL库中的一些函数(例如,RSA_generate_key_ex)来生成RSA密钥,然后使用其他函数(例如,RSA_public_encrypt和RSA_private_decrypt)来进行加密和解密操作。
  • EVP_PKEY:这是一个更通用的密钥表示类型,可以表示各种类型的密钥,包括但不限于RSA密钥。EVP_PKEY对象可以包含RSA密钥、DSA密钥、EC密钥等。使用EVP_PKEY的优点是,你可以编写与密钥类型无关的代码,然后在运行时选择使用哪种类型的密钥。例如,你可以使用相同的EVP_PKEY接口来处理RSA密钥和EC密钥,而不需要为每种密钥类型编写不同的代码。

总的来说,如果你只需要处理RSA密钥,那么使用RSA类型可能会更简单。但是,如果你需要处理多种类型的密钥,或者你想使用OpenSSL的高级加密功能(例如,自动填充模式和摘要算法),那么使用EVP_PKEY可能会更方便。

char* readPublicKeyFromPEM(const char* filePath) {
    FILE* file = fopen(filePath, "r");
    if (file == NULL) {
        printf("file null \r\n");
        return NULL;
    }

    EVP_PKEY* publicKey = PEM_read_PUBKEY(file, NULL, NULL, NULL);
    fclose(file);

    if (publicKey == NULL) {
        // 处理读取公钥错误
        ERR_print_errors_fp(stderr);
        printf("read_PUBKEY error \r\n");
        return NULL;
    }

    BIO* bio = BIO_new(BIO_s_mem());
    PEM_write_bio_PUBKEY(bio, publicKey);

    char* publicKeyStr = NULL;
    long len = BIO_get_mem_data(bio, &publicKeyStr);

    char* result = malloc(len + 1);
    memcpy(result, publicKeyStr, len);
    result[len] = '\0';

	printf("%s \r\n",result);
    BIO_free(bio);
    EVP_PKEY_free(publicKey);

    return result;
}
RSA *publicRsa = NULL;

void ReadPublicKey(void)
{
	
	FILE *fp = NULL;
	if ((fp = fopen("./public.pem", "r")) == NULL) 
	{
		printf("pubkey_path error\n");
		return -1;
	}	

	if ((publicRsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL)) == NULL) 
	{
			printf("PEM_read_RSA_PUBKEY error\n");
			return -1;
	}
	fclose(fp);
	
	int rsa_len = RSA_size(publicRsa);
    BIO* bio = BIO_new(BIO_s_mem());
 
	if (PEM_write_bio_RSAPublicKey(bio, publicRsa) != 1) 
	{
		  // handle error
	}

	char* publicKeyStr = NULL;
    long len = BIO_get_mem_data(bio, &publicKeyStr);

	char* result = malloc(len + 1);
	memcpy(result, publicKeyStr, len);
	result[len] = '\0';

	printf("%s \r\n",result);
	BIO_free(bio);
	RSA_free(publicRsa);

}