2

我正在使用 OpenSSL C API 来构建 CSR。代码如下:

static void seedPRNG() {

const int openSSLseedsize = 128;

uint8_t *openSSLseed = NULL;
openSSLseed = malloc(openSSLseedsize * sizeof(uint8_t));
//printf("%d\n\n", openSSLseedsize);


// random number generator
SecRandomCopyBytes(kSecRandomDefault, openSSLseedsize, openSSLseed);

for (unsigned i = 0; i < openSSLseedsize; i++) {
    printf("%d", openSSLseed[i]);
}
printf("\n\n\n\n");
//seed openSSL random
RAND_seed(openSSLseed, 128);


}

// Parameter settings for this cert
//
#define RSA_KEY_SIZE (2048)
#define ENTRIES 3

// array of entries to assign to cert
struct entry {
char *key;
char *value;
};

struct entry entries[ENTRIES] =
{
{"emailAddress", "tomgrant@example.com"},
{"commonName", "internal.example.com"},
{"countryName", "GB"},
};

// Generate CSR

int generateCSR() {

int i;
RSA *rsakey;
X509_REQ *req;
X509_NAME *subj;
EVP_PKEY *pkey;
EVP_MD *digest;
FILE *fp;

// set up OpenSSl
OpenSSL_add_all_algorithms();
ERR_load_CRYPTO_strings();

// seed oppenssl's prng
seedPRNG();

// generate RSA key (no callback for progress - it's quick enough)
// RSA_F4 is 0x10001 (or 65537) for the exponent.
// RSA docs say exponent should be either 3, 5, 17, 257 or 65537 i.e. prime numbers. See here for further info:
// http://security.stackexchange.com/questions/2335/should-rsa-public-exponent-be-only-in-3-5-17-257-or-65537-due-to-security-c

rsakey = RSA_generate_key(RSA_KEY_SIZE, RSA_F4, NULL, NULL);



if (rsakey == NULL) {
    fatal("Could not create RSA key");
}

// Create EVP ("Envelope Encryption" apparently...) object to hold our rsakey
// generate private key
if (!(pkey = EVP_PKEY_new()))
   fatal("Could not create EVP object");
// assign the rsa key to EVP object
if (!(EVP_PKEY_set1_RSA(pkey, rsakey)))
    fatal("Could not assign RSA key to EVP object");

// create request object
if (!(req = X509_REQ_new()))
    fatal("Failed to create X509_REQ object");

// set the public key
X509_REQ_set_pubkey(req, pkey);


// create and fill in subject object
if (!(subj = X509_NAME_new()))
    fatal("Failed to create X509_NAME object");


for (i = 0; i < ENTRIES; i++)
{
    // create nid for every entry
    int nid; // ASN.1 numeric ID - ASN.1 = Abstract Syntax Notation One. Formal notation used to describe data transmitted by telecommunications protocols.
             // The NID is a unique internal ID assigned to every object. 

    X509_NAME_ENTRY *ent;

    if ((nid = OBJ_txt2nid(entries[i].key)) == NID_undef)
    {
        fprintf(stderr, "Error finding NID for %s\n", entries[i].key);
        fatal("Error on lookup");
    }
    if (!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC, (unsigned char*)entries[i].value, -1)))
        fatal("Error creating Name entry from NID");

    if (X509_NAME_add_entry(subj, ent, -1, 0) != 1)
        fatal("Error adding entry to Name");

}


if (X509_REQ_set_subject_name(req, subj) != 1)
    fatal("Error adding subject to request");

// request is filled in and contains our generated public key
// now sign it
digest = (EVP_MD *)EVP_sha1();

if (!(X509_REQ_sign(req, pkey, digest)))
    fatal("Error signing request");

// write output files
//
NSString *docDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
// append file name
NSString *crtPath = [docDirectory stringByAppendingString:@"/example.crt"];
NSLog(@"crtPath = %@", crtPath);

if (!(fp = fopen([crtPath UTF8String], "w")))
    fatal("Error writing to request file");
if (PEM_write_X509_REQ(fp, req) != 1)
    fatal("Error writing request");
fclose(fp);

NSString *keyPath = [docDirectory stringByAppendingString:@"/example.key"];
NSLog(@"keyPath = %@", keyPath);
if (!(fp = fopen([keyPath UTF8String], "w")))
    fatal("Error writing to private key file");
if (PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, 0, NULL) != 1)
    fatal("Error while writing private key");
fclose(fp);

 X509_REQ_print_fp(stdout, req);


EVP_PKEY_free(pkey);
X509_REQ_free(req);



return 0;

}

这将创建一个 CSR 并输出私钥。我可以使用在线 CSR 检查器来验证 CSR,它会到处打勾,表示它是正确的。我正在使用 Windows 2008R2 CA 粘贴 base64 CSR。但是,当我提交请求时,Windows 框会返回以下错误:

您的请求 ID 为 0。处置消息是“错误解析请求 ASN1 错误标记值。0x8009310b (ASN: 267)”。

使用 open SSL 附带的 mkreq.c 示例代码生成 CSR 时也会发生这种情况。

有没有人遇到过这个?我的在线研究只发现人们从 CA(GoDaddy 等)颁发的时髦证书中得到这个错误。

非常感激任何的帮助!

4

1 回答 1

2

(由 OP 在编辑中回答。请参阅没有答案的问题,但问题已在评论中解决(或在聊天中扩展)

OP写道:

好吧 - 我和我的同事终于找到了解决方案。

查看 ASN.1 表示(使用 openssl asn1parse),我们注意到 BAD CSR 具有以下表示:

8:d=2  hl=2 l=   0 prim: INTEGER           :00

注意 l = 0(我猜这意味着长度)。然后是一个好的企业社会责任:

8:d=2  hl=2 l=   1 prim: INTEGER           :00

注意 l = 1

这可以通过设置 CSR 的版本号来解决(RFP 说它应该设置为 0)。

所以 - 使用 X509_REQ_set_version(req, 0); 有固定的东西和服务器 2008R2 给了我我心爱的身份!

于 2015-01-26T19:47:19.797 回答