问题
I am using the OpenSSL C API to build a CSR. The code is as follows:
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;
}
This creates a CSR and also outputs the private key. I can verify the CSR using an online CSR checker and it comes out with ticks all round saying it is correct. I am using a Windows 2008R2 CA to paste in the base64 CSR. However, when I submit the request, the Windows box throws back the following error:
Your Request Id is 0. The disposition message is "Error Parsing Request ASN1 bad tag value met. 0x8009310b (ASN: 267)".
This also occurs when using the mkreq.c example code that comes with open SSL to generate a CSR.
Has anyone come across this before? My research online has only come up with folks getting this error from funky certs issued from CA's (GoDaddy etc).
Any help would be most appreciated!
回答1:
(Answered by the OP in an edit. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
Well - my colleague and I FINALLY found a solution.
Looking at the ASN.1 representation (using openssl asn1parse), we noticed the BAD CSR had this representation:
8:d=2 hl=2 l= 0 prim: INTEGER :00
Notice the l = 0 (I guess this means length). Then a GOOD CSR:
8:d=2 hl=2 l= 1 prim: INTEGER :00
Notice l = 1
This is fixed by setting the version number of the CSR (the RFP says it should be set to 0).
So - using X509_REQ_set_version(req, 0); has fixed things and server 2008R2 gives me my beloved identity!
来源:https://stackoverflow.com/questions/15294964/windows-2008r2-ca-openssl-csr-error-parsing-csr-asn1-bad-value-met