⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn.cpp

📁 SSL加密库源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    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 + -