📄 asn.cpp
字号:
if (b == TAG_NULL) {
b = source_.next();
if (b != 0) {
source_.SetError(EXPECT_0_E);
return 0;
}
}
else
// go back, didn't have it
b = source_.prev();
return oid;
}
// read cert signature, store in signature_
word32 CertDecoder::GetSignature()
{
if (source_.GetError().What()) return 0;
byte b = source_.next();
if (b != BIT_STRING) {
source_.SetError(BIT_STR_E);
return 0;
}
sigLength_ = GetLength(source_);
b = source_.next();
if (b != 0) {
source_.SetError(EXPECT_0_E);
return 0;
}
sigLength_--;
signature_ = NEW_TC byte[sigLength_];
memcpy(signature_, source_.get_current(), sigLength_);
source_.advance(sigLength_);
return sigLength_;
}
// read cert digest, store in signature_
word32 CertDecoder::GetDigest()
{
if (source_.GetError().What()) return 0;
byte b = source_.next();
if (b != OCTET_STRING) {
source_.SetError(OCTET_STR_E);
return 0;
}
sigLength_ = GetLength(source_);
signature_ = NEW_TC byte[sigLength_];
memcpy(signature_, source_.get_current(), sigLength_);
source_.advance(sigLength_);
return sigLength_;
}
// process NAME, either issuer or subject
void CertDecoder::GetName(NameType nt)
{
if (source_.GetError().What()) return;
SHA sha;
word32 length = GetSequence(); // length of all distinguished names
assert (length < ASN_NAME_MAX);
length += source_.get_index();
char* ptr = (nt == ISSUER) ? issuer_ : subject_;
word32 idx = 0;
while (source_.get_index() < length) {
GetSet();
GetSequence();
byte b = source_.next();
if (b != OBJECT_IDENTIFIER) {
source_.SetError(OBJECT_ID_E);
return;
}
word32 oidSz = GetLength(source_);
byte joint[2];
memcpy(joint, source_.get_current(), sizeof(joint));
// v1 name types
if (joint[0] == 0x55 && joint[1] == 0x04) {
source_.advance(2);
byte id = source_.next();
b = source_.next(); // strType
word32 strLen = GetLength(source_);
bool copy = false;
if (id == COMMON_NAME) {
memcpy(&ptr[idx], "/CN=", 4);
idx += 4;
copy = true;
}
else if (id == SUR_NAME) {
memcpy(&ptr[idx], "/SN=", 4);
idx += 4;
copy = true;
}
else if (id == COUNTRY_NAME) {
memcpy(&ptr[idx], "/C=", 3);
idx += 3;
copy = true;
}
else if (id == LOCALITY_NAME) {
memcpy(&ptr[idx], "/L=", 3);
idx += 3;
copy = true;
}
else if (id == STATE_NAME) {
memcpy(&ptr[idx], "/ST=", 4);
idx += 4;
copy = true;
}
else if (id == ORG_NAME) {
memcpy(&ptr[idx], "/O=", 3);
idx += 3;
copy = true;
}
else if (id == ORGUNIT_NAME) {
memcpy(&ptr[idx], "/OU=", 4);
idx += 4;
copy = true;
}
if (copy) {
memcpy(&ptr[idx], source_.get_current(), strLen);
idx += strLen;
}
sha.Update(source_.get_current(), strLen);
source_.advance(strLen);
}
else {
bool email = false;
if (joint[0] == 0x2a && joint[1] == 0x86) // email id hdr
email = true;
source_.advance(oidSz + 1);
word32 length = GetLength(source_);
if (email) {
memcpy(&ptr[idx], "/emailAddress=", 14);
idx += 14;
memcpy(&ptr[idx], source_.get_current(), length);
idx += length;
}
source_.advance(length);
}
}
ptr[idx++] = 0;
if (nt == ISSUER)
sha.Final(issuerHash_);
else
sha.Final(subjectHash_);
}
// process a Date, either BEFORE or AFTER
void CertDecoder::GetDate(DateType dt)
{
if (source_.GetError().What()) return;
byte b = source_.next();
if (b != UTC_TIME && b != GENERALIZED_TIME) {
source_.SetError(TIME_E);
return;
}
word32 length = GetLength(source_);
byte date[MAX_DATE_SZ];
if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) {
source_.SetError(DATE_SZ_E);
return;
}
memcpy(date, source_.get_current(), length);
source_.advance(length);
if (!ValidateDate(date, b, dt) && verify_)
if (dt == BEFORE)
source_.SetError(BEFORE_DATE_E);
else
source_.SetError(AFTER_DATE_E);
// save for later use
if (dt == BEFORE) {
memcpy(beforeDate_, date, length);
beforeDate_[length] = 0;
}
else { // after
memcpy(afterDate_, date, length);
afterDate_[length] = 0;
}
}
void CertDecoder::GetValidity()
{
if (source_.GetError().What()) return;
GetSequence();
GetDate(BEFORE);
GetDate(AFTER);
}
bool CertDecoder::ValidateSelfSignature()
{
Source pub(key_.GetKey(), key_.size());
return ConfirmSignature(pub);
}
// extract compare signature hash from plain and place into digest
void CertDecoder::GetCompareHash(const byte* plain, word32 sz, byte* digest,
word32 digSz)
{
if (source_.GetError().What()) return;
Source s(plain, sz);
CertDecoder dec(s, false);
dec.GetSequence();
dec.GetAlgoId();
dec.GetDigest();
if (dec.sigLength_ > digSz) {
source_.SetError(SIG_LEN_E);
return;
}
memcpy(digest, dec.signature_, dec.sigLength_);
}
// validate signature signed by someone else
bool CertDecoder::ValidateSignature(SignerList* signers)
{
assert(signers);
SignerList::iterator first = signers->begin();
SignerList::iterator last = signers->end();
while (first != last) {
if ( memcmp(issuerHash_, (*first)->GetHash(), SHA::DIGEST_SIZE) == 0) {
const PublicKey& iKey = (*first)->GetPublicKey();
Source pub(iKey.GetKey(), iKey.size());
return ConfirmSignature(pub);
}
++first;
}
return false;
}
// confirm certificate signature
bool CertDecoder::ConfirmSignature(Source& pub)
{
HashType ht;
mySTL::auto_ptr<HASH> hasher;
if (signatureOID_ == MD5wRSA) {
hasher.reset(NEW_TC MD5);
ht = MD5h;
}
else if (signatureOID_ == MD2wRSA) {
hasher.reset(NEW_TC MD2);
ht = MD2h;
}
else if (signatureOID_ == SHAwRSA || signatureOID_ == SHAwDSA) {
hasher.reset(NEW_TC SHA);
ht = SHAh;
}
else {
source_.SetError(UNKOWN_SIG_E);
return false;
}
byte digest[SHA::DIGEST_SIZE]; // largest size
hasher->Update(source_.get_buffer() + certBegin_, sigIndex_ - certBegin_);
hasher->Final(digest);
if (keyOID_ == RSAk) {
// put in ASN.1 signature format
Source build;
Signature_Encoder(digest, hasher->getDigestSize(), ht, build);
RSA_PublicKey pubKey(pub);
RSAES_Encryptor enc(pubKey);
return enc.SSL_Verify(build.get_buffer(), build.size(), signature_);
}
else { // DSA
// extract r and s from sequence
byte seqDecoded[DSA_SIG_SZ];
DecodeDSA_Signature(seqDecoded, signature_, sigLength_);
DSA_PublicKey pubKey(pub);
DSA_Verifier ver(pubKey);
return ver.Verify(digest, seqDecoded);
}
}
Signature_Encoder::Signature_Encoder(const byte* dig, word32 digSz,
HashType digOID, Source& source)
{
// build bottom up
// Digest
byte digArray[MAX_DIGEST_SZ];
word32 digestSz = SetDigest(dig, digSz, digArray);
// AlgoID
byte algoArray[MAX_ALGO_SZ];
word32 algoSz = SetAlgoID(digOID, algoArray);
// Sequence
byte seqArray[MAX_SEQ_SZ];
word32 seqSz = SetSequence(digestSz + algoSz, seqArray);
source.grow(seqSz + algoSz + digestSz); // make sure enough room
source.add(seqArray, seqSz);
source.add(algoArray, algoSz);
source.add(digArray, digestSz);
}
word32 Signature_Encoder::SetDigest(const byte* d, word32 dSz, byte* output)
{
output[0] = OCTET_STRING;
output[1] = dSz;
memcpy(&output[2], d, dSz);
return dSz + 2;
}
word32 DER_Encoder::SetAlgoID(HashType aOID, byte* output)
{
// adding TAG_NULL and 0 to end
static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
0x05, 0x00 };
static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x02, 0x05, 0x05, 0x00 };
static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x02, 0x02, 0x05, 0x00};
int algoSz = 0;
const byte* algoName = 0;
switch (aOID) {
case SHAh:
algoSz = sizeof(shaAlgoID);
algoName = shaAlgoID;
break;
case MD2h:
algoSz = sizeof(md2AlgoID);
algoName = md2AlgoID;
break;
case MD5h:
algoSz = sizeof(md5AlgoID);
algoName = md5AlgoID;
break;
default:
error_.SetError(UNKOWN_HASH_E);
return 0;
}
byte ID_Length[MAX_LENGTH_SZ];
word32 idSz = SetLength(algoSz - 2, ID_Length); // don't include TAG_NULL/0
byte seqArray[MAX_SEQ_SZ + 1]; // add object_id to end
word32 seqSz = SetSequence(idSz + algoSz + 1, seqArray);
seqArray[seqSz++] = OBJECT_IDENTIFIER;
memcpy(output, seqArray, seqSz);
memcpy(output + seqSz, ID_Length, idSz);
memcpy(output + seqSz + idSz, algoName, algoSz);
return seqSz + idSz + algoSz;
}
word32 SetSequence(word32 len, byte* output)
{
output[0] = SEQUENCE | CONSTRUCTED;
return SetLength(len, output + 1) + 1;
}
word32 EncodeDSA_Signature(const byte* signature, byte* output)
{
Integer r(signature, 20);
Integer s(signature + 20, 20);
return EncodeDSA_Signature(r, s, output);
}
word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output)
{
word32 rSz = r.ByteCount();
word32 sSz = s.ByteCount();
byte rLen[MAX_LENGTH_SZ + 1];
byte sLen[MAX_LENGTH_SZ + 1];
rLen[0] = INTEGER;
sLen[0] = INTEGER;
word32 rLenSz = SetLength(rSz, &rLen[1]) + 1;
word32 sLenSz = SetLength(sSz, &sLen[1]) + 1;
byte seqArray[MAX_SEQ_SZ];
word32 seqSz = SetSequence(rLenSz + rSz + sLenSz + sSz, seqArray);
// seq
memcpy(output, seqArray, seqSz);
// r
memcpy(output + seqSz, rLen, rLenSz);
r.Encode(output + seqSz + rLenSz, rSz);
// s
memcpy(output + seqSz + rLenSz + rSz, sLen, sLenSz);
s.Encode(output + seqSz + rLenSz + rSz + sLenSz, sSz);
return seqSz + rLenSz + rSz + sLenSz + sSz;
}
// put sequence encoded dsa signature into decoded in 2 20 byte integers
word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz)
{
Source source(encoded, sz);
if (source.next() != (SEQUENCE | CONSTRUCTED)) {
source.SetError(SEQUENCE_E);
return 0;
}
GetLength(source); // total
// r
if (source.next() != INTEGER) {
source.SetError(INTEGER_E);
return 0;
}
word32 rLen = GetLength(source);
if (rLen != 20)
if (rLen == 21) { // zero at front, eat
source.next();
--rLen;
}
else if (rLen == 19) { // add zero to front so 20 bytes
decoded[0] = 0;
decoded++;
}
else {
source.SetError(DSA_SZ_E);
return 0;
}
memcpy(decoded, source.get_buffer() + source.get_index(), rLen);
source.advance(rLen);
// s
if (source.next() != INTEGER) {
source.SetError(INTEGER_E);
return 0;
}
word32 sLen = GetLength(source);
if (sLen != 20)
if (sLen == 21) {
source.next(); // zero at front, eat
--sLen;
}
else if (sLen == 19) {
decoded[rLen] = 0; // add zero to front so 20 bytes
decoded++;
}
else {
source.SetError(DSA_SZ_E);
return 0;
}
memcpy(decoded + rLen, source.get_buffer() + source.get_index(), sLen);
source.advance(sLen);
return 40;
}
// Get Cert in PEM format from BEGIN to END
int GetCert(Source& source)
{
char header[] = "-----BEGIN CERTIFICATE-----";
char footer[] = "-----END CERTIFICATE-----";
char* begin = strstr((char*)source.get_buffer(), header);
char* end = strstr((char*)source.get_buffer(), footer);
if (!begin || !end || begin >= end) return -1;
end += strlen(footer);
if (*end == '\r') end++;
Source tmp((byte*)begin, end - begin + 1);
source.Swap(tmp);
return 0;
}
// Decode a BER encoded PKCS12 structure
void PKCS12_Decoder::Decode()
{
ReadHeader();
if (source_.GetError().What()) return;
// Get AuthSafe
GetSequence();
// get object id
byte obj_id = source_.next();
if (obj_id != OBJECT_IDENTIFIER) {
source_.SetError(OBJECT_ID_E);
return;
}
word32 length = GetLength(source_);
word32 algo_sum = 0;
while (length--)
algo_sum += source_.next();
// Get MacData optional
/*
mac digestInfo like certdecoder::getdigest?
macsalt octet string
iter integer
*/
}
void PKCS12_Decoder::ReadHeader()
{
// Gets Version
GetSequence();
GetVersion();
}
// Get Cert in PEM format from pkcs12 file
int GetPKCS_Cert(const char* password, Source& source)
{
PKCS12_Decoder pkcs12(source);
pkcs12.Decode();
return 0;
}
} // namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -