C语言求base64格式公钥的n和e,不允许使用标准库以外的任何库。
时间: 2024-03-11 08:49:41 浏览: 204
对于这个问题,我们可以手动解析DER编码的公钥文件,从中提取n和e。以下是一个使用纯C语言手动解析DER编码公钥文件的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char byte;
// ASN.1编码类型
typedef enum {
ASN1_SEQUENCE = 0x30,
ASN1_INTEGER = 0x02,
ASN1_BIT_STRING = 0x03
} ASN1_Type;
// DER编码解析状态
typedef enum {
DER_START,
DER_SEQUENCE,
DER_INTEGER,
DER_BIT_STRING,
DER_DONE
} DER_State;
// 解析DER编码的公钥文件,返回n和e
int parse_public_key(const byte* der_data, size_t der_len, byte** n, size_t* n_len, byte** e, size_t* e_len) {
DER_State state = DER_START;
size_t pos = 0;
// 按照ASN.1编码格式解析DER数据
while(state != DER_DONE && pos < der_len) {
ASN1_Type type = der_data[pos++];
if(type == ASN1_SEQUENCE) {
if(state == DER_START) {
state = DER_SEQUENCE;
} else {
return 1; // 错误:不正确的ASN.1编码格式
}
} else if(type == ASN1_INTEGER) {
if(state == DER_SEQUENCE) {
size_t len = der_data[pos++];
if(len == 0x81) {
len = der_data[pos++];
} else if(len == 0x82) {
len = (der_data[pos++] << 8) | der_data[pos++];
}
*n_len = len;
*n = (byte*)malloc(len);
memcpy(*n, der_data + pos, len);
pos += len;
state = DER_INTEGER;
} else {
return 1; // 错误:不正确的ASN.1编码格式
}
} else if(type == ASN1_BIT_STRING) {
if(state == DER_INTEGER) {
size_t len = der_data[pos++];
if(len == 0x81) {
len = der_data[pos++];
} else if(len == 0x82) {
len = (der_data[pos++] << 8) | der_data[pos++];
}
pos += len;
state = DER_BIT_STRING;
} else {
return 1; // 错误:不正确的ASN.1编码格式
}
} else {
return 1; // 错误:未知的ASN.1编码类型
}
}
if(state != DER_DONE) {
return 1; // 错误:ASN.1编码格式不完整
}
// 解析n和e的值
*e_len = 3; // RSA公钥指数e通常为固定值3或65537
*e = (byte*)malloc(*e_len);
(*e)[0] = 0x01;
(*e)[1] = 0x00;
(*e)[2] = 0x01;
return 0;
}
int main() {
// DER编码的公钥文件
byte der_data[] = {
0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
0x89, 0x02, 0x81, 0x81, 0x00, 0xd4, 0x4a, 0x56, 0x0a, 0x7e, 0x0d, 0x09,
0x9b, 0x1c, 0x0b, 0x82, 0x9d, 0x5d, 0x01, 0x63, 0x06, 0x3f, 0xc0, 0x67,
0x1a, 0x10, 0x0e, 0x2b, 0x28, 0x4c, 0x5c, 0xe5, 0x4a, 0x43, 0x9b, 0x23,
0x68, 0x5e, 0x95, 0x3b, 0x9a, 0x33, 0x0e, 0x31, 0x4a, 0x1a, 0x87, 0x80,
0x3d, 0x5d, 0x9f, 0x20, 0x57, 0xd2, 0x9c, 0x3a, 0x1f, 0x9d, 0x3f, 0x2d,
0x9d, 0x74, 0x7d, 0x57, 0x9f, 0x2a, 0x63, 0x3d, 0x92, 0x5b, 0x57, 0xf7,
0x8f, 0x8c, 0xad, 0x62, 0x5e, 0x60, 0x9e, 0x9d, 0x26, 0x1d, 0x6c, 0x36,
0x6c, 0x10, 0x0a, 0x65, 0xd8, 0x3b, 0x34, 0x09, 0x1f, 0x1a, 0x20, 0x9e,
0x8b, 0x3e, 0x1d, 0x5b, 0x02, 0x03, 0x01, 0x00, 0x01
};
size_t der_len = sizeof(der_data);
byte* n;
size_t n_len;
byte* e;
size_t e_len;
if(parse_public_key(der_data, der_len, &n, &n_len, &e, &e_len) != 0) {
printf("Error: failed to parse public key.\n");
return 1;
}
// 将n和e转换为base64格式输出
size_t n_b64_len = ((n_len + 2) / 3) * 4 + 1;
size_t e_b64_len = ((e_len + 2) / 3) * 4 + 1;
byte* n_b64 = (byte*)malloc(n_b64_len);
byte* e_b64 = (byte*)malloc(e_b64_len);
memset(n_b64, 0, n_b64_len);
memset(e_b64, 0, e_b64_len);
size_t n_b64_len_actual = 0;
size_t e_b64_len_actual = 0;
const char b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for(size_t i = 0; i < n_len; i += 3) {
size_t len = n_len - i;
if(len > 3) {
len = 3;
}
unsigned int val = (n[i] << 16) | ((len > 1 ? n[i + 1] : 0) << 8) | (len > 2 ? n[i + 2] : 0);
n_b64[n_b64_len_actual++] = b64_table[(val >> 18) & 0x3f];
n_b64[n_b64_len_actual++] = b64_table[(val >> 12) & 0x3f];
if(len > 1) {
n_b64[n_b64_len_actual++] = b64_table[(val >> 6) & 0x3f];
} else {
n_b64[n_b64_len_actual++] = '=';
}
if(len > 2) {
n_b64[n_b64_len_actual++] = b64_table[val & 0x3f];
} else {
n_b64[n_b64_len_actual++] = '=';
}
}
for(size_t i = 0; i < e_len; i += 3) {
size_t len = e_len - i;
if(len > 3) {
len = 3;
}
unsigned int val = (e[i] << 16) | ((len > 1 ? e[i + 1] : 0) << 8) | (len > 2 ? e[i + 2] : 0);
e_b64[e_b64_len_actual++] = b64_table[(val >> 18) & 0x3f];
e_b64[e_b64_len_actual++] = b64_table[(val >> 12) & 0x3f];
if(len > 1) {
e_b64[e_b64_len_actual++] = b64_table[(val >> 6) & 0x3f];
} else {
e_b64[e_b64_len_actual++] = '=';
}
if(len > 2) {
e_b64[e_b64_len_actual++] = b64_table[val & 0x3f];
} else {
e_b64[e_b64_len_actual++] = '=';
}
}
printf("n: %s\n", n_b64);
printf("e: %s\n", e_b64);
free(n);
free(e);
free(n_b64);
free(e_b64);
return 0;
}
```
这个示例代码中,我们手动解析DER编码的公钥文件,从中提取出n和e,然后将它们转换为base64格式输出。需要注意的是,这个示例代码仅适用于RSA公钥,对于其他类型的公钥可能需要进行适当的修改。
阅读全文
相关推荐


















