目录
Task 1: Deriving the Private Key
Task 6: Manually Verifying an X.509 Certificate
Step 1: Download a certificate from a real web server.
Step 2: Extract the public key (e, n) from the issuer’s certificate.
Step 3: Extract the signature from the server’s certificate.
Step 4: Extract the body of the server’s certificate.
测试示例
gcc bn_sample.c -lcrypto
Task 1: Deriving the Private Key
代码如下
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 256
void printBN(char *msg, BIGNUM * a)
{
/* Use BN_bn2hex(a) for hex string
* Use BN_bn2dec(a) for decimal string */
char * number_str = BN_bn2hex(a);
printf("%s %s\n", msg, number_str);
OPENSSL_free(number_str);
}
int main ()
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *p = BN_new();
BIGNUM *q = BN_new();
BIGNUM *n = BN_new();
BIGNUM *p_ = BN_new();
BIGNUM *q_ = BN_new();
BIGNUM *n_ = BN_new();
BIGNUM *e = BN_new();
BIGNUM *d = BN_new();
BN_hex2bn(&p, "F7E75FDC469067FFDC4E847C51F452DF");
BN_hex2bn(&q, "E85CED54AF57E53E092113E62F436F4F");
BN_hex2bn(&e, "0D88C3");
BN_sub(p_, p, BN_value_one()); //p-1
BN_sub(q_, q, BN_value_one()); //q-1
BN_mul(n, p, q, ctx); //n
BN_mul(n_, p_, q_, ctx); //φ(n)
BN_mod_inverse(d, e, n_, ctx); //ed mod φ(n)=1
printBN("p = ", p);
printBN("q = ", q);
printBN("e = ", e);
printBN("n = ", n);
printBN("d = ", d);
return 0;
}
Task 2: Encrypting a Message
其需要加密的十六进制串为4120746f702073656372657421
代码如下
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 256
void printBN(char *msg, BIGNUM * a)
{
/* Use BN_bn2hex(a) for hex string
* Use BN_bn2dec(a) for decimal string */
char * number_str = BN_bn2hex(a);
printf("%s %s\n", msg, number_str);
OPENSSL_free(number_str);
}
int main ()
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *n = BN_new();
BIGNUM *e = BN_new();
BIGNUM *m = BN_new();
BIGNUM *c = BN_new();
BN_hex2bn(&n, "DCBFFE3E51F62E09CE7032E2677A78946A849DC4CDDE3A4D0CB81629242FB1A5");
BN_hex2bn(&e, "010001");
BN_hex2bn(&m, "4120746f702073656372657421");
BN_mod_exp(c, m, e, n, ctx); //c=m^e mod n
printBN("c = ", c);
return 0;
}
Task 3: Decrypting a Message
代码如下
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 256
void printBN(char *msg, BIGNUM * a)
{
/* Use BN_bn2hex(a) for hex string
* Use BN_bn2dec(a) for decimal string */
char * number_str = BN_bn2hex(a);
printf("%s %s\n", msg, number_str);
OPENSSL_free(number_str);
}
int main ()
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *n = BN_new();
BIGNUM *e = BN_new();
BIGNUM *d = BN_new();
BIGNUM *m = BN_new();
BIGNUM *c = BN_new();
BN_hex2bn(&n, "DCBFFE3E51F62E09CE7032E2677A78946A849DC4CDDE3A4D0CB81629242FB1A5");
BN_hex2bn(&e, "010001");
BN_hex2bn(&d, "74D806F9F3A62BAE331FFE3F0A68AFE35B3D2E4794148AACBC26AA381CD7D30D");
BN_hex2bn(&c, "6FB078DA550B2650832661E14F4F8D2CFAEF475A0DF3A75CACDC5DE5CFC5FADC");
BN_mod_exp(m, c, d, n, ctx); //m=c^d mod n
printBN("m = ", m);
return 0;
}
Task 4: Signing a Message
代码如下
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 256
void printBN(char *msg, BIGNUM * a)
{
/* Use BN_bn2hex(a) for hex string
* Use BN_bn2dec(a) for decimal string */
char * number_str = BN_bn2hex(a);
printf("%s %s\n", msg, number_str);
OPENSSL_free(number_str);
}
int main ()
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *n = BN_new();
BIGNUM *e = BN_new();
BIGNUM *d = BN_new();
BIGNUM *M1 = BN_new();
BIGNUM *M2 = BN_new();
BIGNUM *S1 = BN_new();
BIGNUM *S2 = BN_new();
BN_hex2bn(&n, "DCBFFE3E51F62E09CE7032E2677A78946A849DC4CDDE3A4D0CB81629242FB1A5");
BN_hex2bn(&e, "010001");
BN_hex2bn(&d, "74D806F9F3A62BAE331FFE3F0A68AFE35B3D2E4794148AACBC26AA381CD7D30D");
BN_hex2bn(&M1, "49206f776520796f752024323030302e");
BN_hex2bn(&M2, "49206f776520796f752024333030302e");
BN_mod_exp(S1, M1, d, n, ctx); //S1=M1^d mod n
BN_mod_exp(S2, M2, d, n, ctx); //S2=M2^d mod n
printBN("S1 = ", S1);
printBN("S2 = ", S2);
return 0;
}
可以看到虽然消息的变动很微小,但签名之后是完全不同的。
Task 5: Verifying a Signature
代码如下
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 256
void printBN(char *msg, BIGNUM * a)
{
/* Use BN_bn2hex(a) for hex string
* Use BN_bn2dec(a) for decimal string */
char * number_str = BN_bn2hex(a);
printf("%s %s\n", msg, number_str);
OPENSSL_free(number_str);
}
int main ()
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *n = BN_new();
BIGNUM *e = BN_new();
BIGNUM *M = BN_new();
BIGNUM *S1 = BN_new();
BIGNUM *S2 = BN_new();
BIGNUM *M1 = BN_new();
BIGNUM *M2 = BN_new();
BN_hex2bn(&n, "AE1CD4DC432798D933779FBD46C6E1247F0CF1233595113AA51B450F18116115");
BN_hex2bn(&e, "010001");
BN_hex2bn(&M, "4c61756e63682061206d697373696c652e");
BN_hex2bn(&S1, "643D6F34902D9C7EC90CB0B2BCA36C47FA37165C0005CAB026C0542CBDB6802F");
BN_hex2bn(&S2, "643D6F34902D9C7EC90CB0B2BCA36C47FA37165C0005CAB026C0542CBDB6803F");
BN_mod_exp(M1, S1, e, n, ctx); //M1=S1^e mod n
BN_mod_exp(M2, S2, e, n, ctx); //M2=S2^e mod n
if (BN_cmp(M1, M)==0)
printf("S1:Valid\n");
else
printf("S1:Not valid\n");
if (BN_cmp(M2, M)==0)
printf("S2:Valid\n");
else
printf("S2:Not valid\n");
return 0;
}
Task 6: Manually Verifying an X.509 Certificate
Step 1: Download a certificate from a real web server.
Step 2: Extract the public key (e, n) from the issuer’s certificate.
可以看到e为65537
Step 3: Extract the signature from the server’s certificate.
将签名复制到文件中
Step 4: Extract the body of the server’s certificate.
Step 5: Verify the signature.
代码如下
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 256
void printBN(char *msg, BIGNUM * a)
{
/* Use BN_bn2hex(a) for hex string
* Use BN_bn2dec(a) for decimal string */
char * number_str = BN_bn2hex(a);
printf("%s %s\n", msg, number_str);
OPENSSL_free(number_str);
}
int main ()
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *n = BN_new();
BIGNUM *e = BN_new();
BIGNUM *M = BN_new();
BIGNUM *S = BN_new();
BN_hex2bn(&n, "CCF710624FA6BB636FED905256C56D277B7A12568AF1F4F9D6E7E18FBD95ABF260411570DB1200FA270AB557385B7DB2519371950E6A41945B351BFA7BFABBC5BE2430FE56EFC4F37D97E314F5144DCBA710F216EAAB22F031221161699026BA78D9971FE37D66AB75449573C8ACFFEF5D0A8A5943E1ACB23A0FF348FCD76B37C163DCDE46D6DB45FE7D23FD90E851071E51A35FED4946547F2C88C5F4139C97153C03E8A139DC690C32C1AF16574C9447427CA2C89C7DE6D44D54AF4299A8C104C2779CD648E4CE11E02A8099F04370CF3F766BD14C49AB245EC20D82FD46A8AB6C93CC6252427592F89AFA5E5EB2B061E51F1FB97F0998E83DFA837F4769A1");
BN_hex2bn(&e, "10001");
BN_hex2bn(&S, "04e16e023e0de32346f4e3963505933522020b845de27386d4744ffc1b27af3ecaadc3ce46d6fa0fe271f90d1a9a13b7d50848bd5058b35e20638629ca3ecccc7826e1598f5dca8bbc49316f61bd42ff6162e1223524269b57ebe5000dff40336c46c233770898b27af643f96d48dfbffefa281e7b8acf2d61ff6c8798a42c629abb108cff34487066b76d72c369f9394b683956bda1b36df477f3465b5c19ac4fb3746b8cc5f189cc93fe0c016f8817dc427160e3ed7330429ca92f3ba2788ec86fbad1130cd0c75e8c10fb012e379bdbacf7a1acba7ff892e7cb4144c815f9f3c4bbad515fbedec7ac86079f40ecb90bf6b28bccb5553366ba33c2c4f0a2e9");
BN_mod_exp(M, S, e, n, ctx); //M=S^e mod n
printBN("M = ", M);
return 0;
}
经验证其后256比特位与第四步得到的哈希值一致