📄 asn.cpp
字号:
// Save public keyvoid CertDecoder::StoreKey(){ if (source_.GetError().What()) return; word32 read = source_.get_index(); word32 length = GetSequence(); read = source_.get_index() - read; length += read; while (read--) source_.prev(); key_.SetSize(length); key_.SetKey(source_.get_current()); source_.advance(length);}// DSA has public key after groupvoid CertDecoder::AddDSA(){ if (source_.GetError().What()) return; byte b = source_.next(); if (b != BIT_STRING) { source_.SetError(BIT_STR_E); return; } b = source_.next(); // length, future b = source_.next(); while(b != 0) b = source_.next(); word32 idx = source_.get_index(); b = source_.next(); if (b != INTEGER) { source_.SetError(INTEGER_E); return; } word32 length = GetLength(source_); length += source_.get_index() - idx; key_.AddToEnd(source_.get_buffer() + idx, length); }// process algo OID by summing, return itword32 CertDecoder::GetAlgoId(){ if (source_.GetError().What()) return 0; word32 length = GetSequence(); byte b = source_.next(); if (b != OBJECT_IDENTIFIER) { source_.SetError(OBJECT_ID_E); return 0; } length = GetLength(source_); word32 oid = 0; while(length--) oid += source_.next(); // just sum it up for now if (oid != SHAwDSA && oid != DSAk) { b = source_.next(); // should have NULL tag and 0 if (b != TAG_NULL) { source_.SetError(TAG_NULL_E); return 0; } b = source_.next(); if (b != 0) { source_.SetError(EXPECT_0_E); return 0; } } 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 subjectvoid CertDecoder::GetName(NameType nt){ if (source_.GetError().What()) return; SHA sha; word32 length = GetSequence(); // length of all distinguished names length += source_.get_index(); 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_); if (id == COMMON_NAME) { char*& ptr = (nt == ISSUER) ? issuer_ : subject_; ptr = new (tc) char[strLen + 1]; memcpy(ptr, source_.get_current(), strLen); ptr[strLen] = 0; } sha.Update(source_.get_current(), strLen); source_.advance(strLen); } else { // skip source_.advance(oidSz + 1); word32 length = GetLength(source_); source_.advance(length); } } if (nt == ISSUER) sha.Final(issuerHash_); else sha.Final(subjectHash_);}// process a Date, either BEFORE or AFTERvoid 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)) if (dt == BEFORE) source_.SetError(BEFORE_DATE_E); else source_.SetError(AFTER_DATE_E);}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 digestvoid 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 elsebool 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;}// RSA confirmbool CertDecoder::ConfirmSignature(Source& pub){ HashType ht; mySTL::auto_ptr<HASH> hasher(tcDelete); 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 integersword32 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;}} // namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -