/* */ #include "MessageDigestHelper.h" #include "messageDigest.h" #include "DlAbortEx.h" #include "message.h" #include "DefaultDiskWriter.h" #include "Util.h" #include namespace aria2 { MessageDigestContext* MessageDigestHelper::_sha1Ctx = 0; void MessageDigestHelper::staticSHA1DigestInit() { staticSHA1DigestFree(); _sha1Ctx = new MessageDigestContext(); _sha1Ctx->trySetAlgo("sha1"); _sha1Ctx->digestInit(); } void MessageDigestHelper::staticSHA1DigestFree() { delete _sha1Ctx; } std::string MessageDigestHelper::staticSHA1Digest(const BinaryStreamHandle& bs, off_t offset, uint64_t length) { _sha1Ctx->digestReset(); return digest(_sha1Ctx, bs, offset, length); } std::string MessageDigestHelper::digest(const std::string& algo, const BinaryStreamHandle& bs, off_t offset, uint64_t length) { MessageDigestContext ctx; ctx.trySetAlgo(algo); ctx.digestInit(); return digest(&ctx, bs, offset, length); } std::string MessageDigestHelper::digest(MessageDigestContext* ctx, const SharedHandle& bs, off_t offset, uint64_t length) { size_t BUFSIZE = 4096; unsigned char BUF[BUFSIZE]; lldiv_t res = lldiv(length, BUFSIZE); uint64_t iteration = res.quot; size_t tail = res.rem; for(uint64_t i = 0; i < iteration; ++i) { ssize_t readLength = bs->readData(BUF, BUFSIZE, offset); if((size_t)readLength != BUFSIZE) { throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno)); } ctx->digestUpdate(BUF, readLength); offset += readLength; } if(tail) { ssize_t readLength = bs->readData(BUF, tail, offset); if((size_t)readLength != tail) { throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno)); } ctx->digestUpdate(BUF, readLength); } std::string rawMD = ctx->digestFinal(); return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size()); } std::string MessageDigestHelper::digest(const std::string& algo, const std::string& filename) { DiskWriterHandle writer(new DefaultDiskWriter()); writer->openExistingFile(filename); return digest(algo, writer, 0, writer->size()); } std::string MessageDigestHelper::digest(const std::string& algo, const void* data, size_t length) { MessageDigestContext ctx; ctx.trySetAlgo(algo); ctx.digestInit(); ctx.digestUpdate(data, length); std::string rawMD = ctx.digestFinal(); return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size()); } void MessageDigestHelper::digest(unsigned char* md, size_t mdLength, const std::string& algo, const void* data, size_t length) { if(mdLength < MessageDigestContext::digestLength(algo)) { throw new DlAbortEx("Insufficient space for storing message digest: %d required, but only %d is allocated", MessageDigestContext::digestLength(algo), mdLength); } MessageDigestContext ctx; ctx.trySetAlgo(algo); ctx.digestInit(); ctx.digestUpdate(data, length); ctx.digestFinal(md); } } // namespace aria2