吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1408|回复: 24
收起左侧

[C&C++ 原创] 增强7-zip的加密算法,添加XChaCha20/XChaCha20-Poly1305

[复制链接]
风之暇想 发表于 2026-5-28 08:54

压缩包历来只有AES算法,没得选择,但现在你有得选了;增强版7-zip增加XChaCha20/XChaCha20-Poly1305加密算法。

截图

7zG_VAwUu5QgyP.png

部分代码

// XChaCha20.cpp

#include "StdAfx.h"

#include "../../../C/CpuArch.h"

#include "../../Common/ComTry.h"

#ifndef Z7_ST
#include "../../Windows/Synchronization.h"
#endif

#include "../Common/StreamUtils.h"

#include "XChaCha20.h"

#ifndef Z7_EXTRACT_ONLY
#include "RandGen.h"
#endif

#include "ChaCha20Simd.h"

namespace NCrypto {
namespace NXChaCha20 {

#define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n))))

#define QUARTERROUND(a, b, c, d) \
  a += b; d ^= a; d = ROTL32(d, 16); \
  c += d; b ^= c; b = ROTL32(b, 12); \
  a += b; d ^= a; d = ROTL32(d, 8); \
  c += d; b ^= c; b = ROTL32(b, 7);

#define CHACHA20_10_DOUBLE_ROUNDS \
  DOUBLE_ROUND; DOUBLE_ROUND; \
  DOUBLE_ROUND; DOUBLE_ROUND; \
  DOUBLE_ROUND; DOUBLE_ROUND; \
  DOUBLE_ROUND; DOUBLE_ROUND; \
  DOUBLE_ROUND; DOUBLE_ROUND;

static CKeyInfoCache g_GlobalKeyCache(32);

#ifndef Z7_ST
  static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
#else
  #define MT_LOCK
#endif

CBase::CBase():
  _cachedKeys(16),
  _counter(0)
{
  for (unsigned i = 0; i < sizeof(_nonce); i++)
    _nonce[i] = 0;
}

void CBaseCoder::DeriveKey()
{
  XHChaCha20Block_Core(_derivedKey, _key.Key, _nonce);
  _derivedKeyValid = true;
}

void CBase::PrepareKey()
{
  MT_LOCK

  bool finded = false;
  if (!_cachedKeys.GetKey(_key))
  {
    finded = g_GlobalKeyCache.GetKey(_key);
    if (!finded)
      _key.CalcKey();
    _cachedKeys.Add(_key);
  }
  if (!finded)
    g_GlobalKeyCache.FindAndAdd(_key);
}

void XHChaCha20Block_Core(Byte *output, const Byte *key, const Byte *nonce)
{
  UInt32 x0, x1, x2, x3, x4, x5, x6, x7;
  UInt32 x8, x9, x10, x11, x12, x13, x14, x15;

  x0 = GetUi32(kSigma);
  x1 = GetUi32(kSigma + 4);
  x2 = GetUi32(kSigma + 8);
  x3 = GetUi32(kSigma + 12);

  x4 = GetUi32(key);
  x5 = GetUi32(key + 4);
  x6 = GetUi32(key + 8);
  x7 = GetUi32(key + 12);
  x8 = GetUi32(key + 16);
  x9 = GetUi32(key + 20);
  x10 = GetUi32(key + 24);
  x11 = GetUi32(key + 28);

  x12 = GetUi32(nonce);
  x13 = GetUi32(nonce + 4);
  x14 = GetUi32(nonce + 8);
  x15 = GetUi32(nonce + 12);

#define DOUBLE_ROUND \
  QUARTERROUND(x0, x4, x8,  x12) \
  QUARTERROUND(x1, x5, x9,  x13) \
  QUARTERROUND(x2, x6, x10, x14) \
  QUARTERROUND(x3, x7, x11, x15) \
  QUARTERROUND(x0, x5, x10, x15) \
  QUARTERROUND(x1, x6, x11, x12) \
  QUARTERROUND(x2, x7, x8,  x13) \
  QUARTERROUND(x3, x4, x9,  x14)

  CHACHA20_10_DOUBLE_ROUNDS

#undef DOUBLE_ROUND

  SetUi32(output, x0);
  SetUi32(output + 4, x1);
  SetUi32(output + 8, x2);
  SetUi32(output + 12, x3);
  SetUi32(output + 16, x12);
  SetUi32(output + 20, x13);
  SetUi32(output + 24, x14);
  SetUi32(output + 28, x15);
}

void XChaCha20Block_Core(Byte *output, const Byte *key, const Byte *nonce, UInt64 counter)
{
  UInt32 x0, x1, x2, x3, x4, x5, x6, x7;
  UInt32 x8, x9, x10, x11, x12, x13, x14, x15;

  x0 = GetUi32(kSigma);
  x1 = GetUi32(kSigma + 4);
  x2 = GetUi32(kSigma + 8);
  x3 = GetUi32(kSigma + 12);

  x4 = GetUi32(key);
  x5 = GetUi32(key + 4);
  x6 = GetUi32(key + 8);
  x7 = GetUi32(key + 12);
  x8 = GetUi32(key + 16);
  x9 = GetUi32(key + 20);
  x10 = GetUi32(key + 24);
  x11 = GetUi32(key + 28);

  x12 = (UInt32)(counter & 0xFFFFFFFF);
  x13 = (UInt32)(counter >> 32);
  x14 = GetUi32(nonce);
  x15 = GetUi32(nonce + 4);

#define DOUBLE_ROUND \
  QUARTERROUND(x0, x4, x8,  x12) \
  QUARTERROUND(x1, x5, x9,  x13) \
  QUARTERROUND(x2, x6, x10, x14) \
  QUARTERROUND(x3, x7, x11, x15) \
  QUARTERROUND(x0, x5, x10, x15) \
  QUARTERROUND(x1, x6, x11, x12) \
  QUARTERROUND(x2, x7, x8,  x13) \
  QUARTERROUND(x3, x4, x9,  x14)

  CHACHA20_10_DOUBLE_ROUNDS

#undef DOUBLE_ROUND

  x0 += GetUi32(kSigma);
  x1 += GetUi32(kSigma + 4);
  x2 += GetUi32(kSigma + 8);
  x3 += GetUi32(kSigma + 12);
  x4 += GetUi32(key);
  x5 += GetUi32(key + 4);
  x6 += GetUi32(key + 8);
  x7 += GetUi32(key + 12);
  x8 += GetUi32(key + 16);
  x9 += GetUi32(key + 20);
  x10 += GetUi32(key + 24);
  x11 += GetUi32(key + 28);
  x12 += (UInt32)(counter & 0xFFFFFFFF);
  x13 += (UInt32)(counter >> 32);
  x14 += GetUi32(nonce);
  x15 += GetUi32(nonce + 4);

  SetUi32(output, x0)
  SetUi32(output + 4, x1)
  SetUi32(output + 8, x2)
  SetUi32(output + 12, x3)
  SetUi32(output + 16, x4)
  SetUi32(output + 20, x5)
  SetUi32(output + 24, x6)
  SetUi32(output + 28, x7)
  SetUi32(output + 32, x8)
  SetUi32(output + 36, x9)
  SetUi32(output + 40, x10)
  SetUi32(output + 44, x11)
  SetUi32(output + 48, x12)
  SetUi32(output + 52, x13)
  SetUi32(output + 56, x14)
  SetUi32(output + 60, x15)
}

void CBaseCoder::ProcessData(Byte *data, UInt32 size)
{
  if (!_derivedKeyValid)
  {
    DeriveKey();
  }

#ifdef MY_CPU_X86_OR_AMD64
#ifdef MY_CPU_SSE2
  InitSIMD();

  if (size >= kBlockSize * 4)
  {
    UInt32 state[16];
    state[0] = GetUi32(kSigma);
    state[1] = GetUi32(kSigma + 4);
    state[2] = GetUi32(kSigma + 8);
    state[3] = GetUi32(kSigma + 12);
    state[4] = GetUi32(_derivedKey);
    state[5] = GetUi32(_derivedKey + 4);
    state[6] = GetUi32(_derivedKey + 8);
    state[7] = GetUi32(_derivedKey + 12);
    state[8] = GetUi32(_derivedKey + 16);
    state[9] = GetUi32(_derivedKey + 20);
    state[10] = GetUi32(_derivedKey + 24);
    state[11] = GetUi32(_derivedKey + 28);
    state[12] = (UInt32)(_counter & 0xFFFFFFFF);
    state[13] = (UInt32)(_counter >> 32);
    state[14] = GetUi32(_nonce + 16);
    state[15] = GetUi32(_nonce + 20);

#ifdef MY_CPU_AMD64
    if (g_AVX2Enabled && size >= kBlockSize * 8)
    {
      while (size >= kBlockSize * 8)
      {
        ChaCha20_OperateKeystream_AVX2(state, data, data);
        state[12] += 8;
        if (state[12] < 8)
          state[13]++;
        data += kBlockSize * 8;
        size -= kBlockSize * 8;
      }
    }
#endif

    if (g_SSE2Enabled && size >= kBlockSize * 4)
    {
      while (size >= kBlockSize * 4)
      {
        ChaCha20_OperateKeystream_SSE2(state, data, data);
        state[12] += 4;
        if (state[12] < 4)
          state[13]++;
        data += kBlockSize * 4;
        size -= kBlockSize * 4;
      }
    }

    _counter = (UInt64)state[13] << 32 | state[12];
  }
#endif
#endif

#ifdef MY_CPU_ARM_OR_ARM64
  InitSIMD();

  if (g_NEONEnabled && size >= kBlockSize * 4)
  {
    UInt32 state[16];
    state[0] = GetUi32(kSigma);
    state[1] = GetUi32(kSigma + 4);
    state[2] = GetUi32(kSigma + 8);
    state[3] = GetUi32(kSigma + 12);
    state[4] = GetUi32(_derivedKey);
    state[5] = GetUi32(_derivedKey + 4);
    state[6] = GetUi32(_derivedKey + 8);
    state[7] = GetUi32(_derivedKey + 12);
    state[8] = GetUi32(_derivedKey + 16);
    state[9] = GetUi32(_derivedKey + 20);
    state[10] = GetUi32(_derivedKey + 24);
    state[11] = GetUi32(_derivedKey + 28);
    state[12] = (UInt32)(_counter & 0xFFFFFFFF);
    state[13] = (UInt32)(_counter >> 32);
    state[14] = GetUi32(_nonce + 16);
    state[15] = GetUi32(_nonce + 20);

    while (size >= kBlockSize * 4)
    {
      ChaCha20_OperateKeystream_NEON(state, data, data);
      state[12] += 4;
      if (state[12] < 4)
        state[13]++;
      data += kBlockSize * 4;
      size -= kBlockSize * 4;
    }

    _counter = (UInt64)state[13] << 32 | state[12];
  }
#endif

  while (size > 0)
  {
    if (_blockPos == 0 || _blockPos >= kBlockSize)
    {
      XChaCha20Block_Core(_block, _derivedKey, _nonce + 16, _counter);
      _blockPos = 0;
      _counter++;
    }

    UInt32 remaining = kBlockSize - _blockPos;
    UInt32 toProcess = (size < remaining) ? size : remaining;

    Byte *dataPtr = data;
    const Byte *blockPtr = _block + _blockPos;
    UInt32 count = toProcess;

#ifdef MY_CPU_64BIT
    while (count >= 8)
    {
      *(UInt64 *)dataPtr ^= *(const UInt64 *)blockPtr;
      dataPtr += 8;
      blockPtr += 8;
      count -= 8;
    }
#endif

    while (count >= 4)
    {
      *(UInt32 *)dataPtr ^= *(const UInt32 *)blockPtr;
      dataPtr += 4;
      blockPtr += 4;
      count -= 4;
    }

    while (count--)
      *dataPtr++ ^= *blockPtr++;

    data += toProcess;
    size -= toProcess;
    _blockPos += toProcess;
  }
}

#ifndef Z7_EXTRACT_ONLY

Z7_COM7F_IMF(CEncoder::ResetInitVector())
{
  for (unsigned i = 0; i < sizeof(_nonce); i++)
    _nonce[i] = 0;
  MY_RAND_GEN(_nonce, kNonceSize);
  _counter = 0;
  _blockPos = kBlockSize;
  _derivedKeyValid = false;
  return S_OK;
}

Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))
{
  Byte props[2 + sizeof(_key.Salt) + kNonceSize];
  unsigned propsSize = 1;

  const unsigned nonceSizeMinus1 = kNonceSize - 1;
  const unsigned nonceHigh = (nonceSizeMinus1 >= 16) ? (1 << 6) : 0;
  const unsigned nonceLow = nonceSizeMinus1 & 0x0F;

  props[0] = (Byte)(_key.NumCyclesPower
      | (_key.SaltSize == 0 ? 0 : (1 << 7))
      | nonceHigh);

  if (_key.SaltSize != 0)
  {
    props[1] = (Byte)(
        ((_key.SaltSize - 1) << 4)
        | nonceLow);
    memcpy(props + 2, _key.Salt, _key.SaltSize);
    propsSize = 2 + _key.SaltSize;
    memcpy(props + propsSize, _nonce, kNonceSize);
    propsSize += kNonceSize;
  }
  else
  {
    props[1] = (Byte)(nonceLow);
    propsSize = 2;
    memcpy(props + propsSize, _nonce, kNonceSize);
    propsSize += kNonceSize;
  }

  return WriteStream(outStream, props, propsSize);
}

CEncoder::CEncoder()
{
  _key.NumCyclesPower = 19;
  _counter = 0;
  _blockPos = kBlockSize;
  _derivedKeyValid = false;
}

#endif

CDecoder::CDecoder()
{
  _counter = 0;
  _blockPos = kBlockSize;
  _derivedKeyValid = false;
}

Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))
{
  _key.ClearProps();

  _counter = 0;
  _blockPos = kBlockSize;
  _derivedKeyValid = false;
  unsigned i;
  for (i = 0; i < sizeof(_nonce); i++)
    _nonce[i] = 0;

  if (size == 0)
    return S_OK;

  const unsigned b0 = data[0];
  _key.NumCyclesPower = b0 & 0x3F;
  if ((b0 & 0xC0) == 0)
    return size == 1 ? S_OK : E_INVALIDARG;
  if (size <= 1)
    return E_INVALIDARG;

  const unsigned b1 = data[1];
  const unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);
  const unsigned nonceSizeMinus1 = ((b0 >> 6) & 1) * 16 + (b1 & 0x0F);
  const unsigned nonceSize = nonceSizeMinus1 + 1;

  if (size != 2 + saltSize + nonceSize)
    return E_INVALIDARG;
  _key.SaltSize = saltSize;
  data += 2;
  for (i = 0; i < saltSize; i++)
    _key.Salt[i] = *data++;
  for (i = 0; i < nonceSize && i < kNonceSize; i++)
    _nonce[i] = *data++;

  return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX
      || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL;
}

Z7_COM7F_IMF(CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size))
{
  COM_TRY_BEGIN

  _key.Password.Wipe();
  _key.Password.CopyFrom(data, (size_t)size);
  _derivedKeyValid = false;
  return S_OK;

  COM_TRY_END
}

Z7_COM7F_IMF(CBaseCoder::Init())
{
  COM_TRY_BEGIN

  PrepareKey();
  _counter = 0;
  _blockPos = kBlockSize;
  _derivedKeyValid = false;
  return S_OK;

  COM_TRY_END
}

Z7_COM7F_IMF2(UInt32, CBaseCoder::Filter(Byte *data, UInt32 size))
{
  ProcessData(data, size);
  return size;
}

}}

开源地址

已提交给7-zip官方,如果没有被采纳,将会分离作为独立项目
https://github.com/fzxx/7zip-XChaCha20

免费评分

参与人数 6威望 +1 吾爱币 +25 热心值 +6 收起 理由
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
天业电子 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
wanfon + 1 + 1 热心回复!
anotherNEw + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ParllelShifterX + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
293a + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jerrylee0521 发表于 2026-5-28 09:28
大佬都是nb,软件没有的功能自己开发,用的好给官方提交建议,不采纳自己拆分支!
aimer 发表于 2026-6-3 02:06
风之暇想 发表于 2026-5-28 09:59
不是;64位8字节处理 → 4字节处理 → 1字节处理,32位4字节处理 → 1字节处理。

UInt32/UInt64 是无符号固定宽度整数 .      // 64-8-4-1 ?   32-4-1?   内存对齐有隐患吧?

#  UInt32/UInt64 是无符号固定宽度整数,需要头文件或自定义 .

typedef unsigned int    UInt32;
typedef unsigned long long UInt64;


直接 (UInt64*)dataPtr 强制转换的话dataPtr/blockPtr地址不是 8 字节对齐:ARM、部分 RISC 架构触发总线对齐异常崩溃;x86/x64 非对齐能跑但性能会暴跌的!


代码是否可以这么写呢?

#include <stdint.h>
typedef uint32_t UInt32;
typedef uint64_t UInt64;

// in-place 内存异或
void mem_xor(uint8_t* dataPtr, const uint8_t* blockPtr, size_t count)
{
#ifdef MY_CPU_64BIT
    while (count >= 8)
    {
        *(UInt64 *)dataPtr ^= *(const UInt64 *)blockPtr;
        dataPtr += 8;
        blockPtr += 8;
        count -= 8;
    }
#endif
    while (count >= 4)
    {
        *(UInt32 *)dataPtr ^= *(const UInt32 *)blockPtr;
        dataPtr += 4;
        blockPtr += 4;
        count -= 4;
    }
    // 剩余1~3字节
    while(count--)
    {
        *dataPtr++ ^= *blockPtr++;
    }
}


//  纯交流, 没有别的意思, 还望大佬见谅!!!!




点评

是有隐患,已修复(见Github)  详情 回复 发表于 2026-6-3 09:15
ghostOfTheWolf 发表于 2026-5-28 09:00
这种通用软件的加密方式修改如果不能合并到主线,那就只适合小范围用.希望7zip官方能够合并进去
aluo5299 发表于 2026-5-28 09:03
个人需求在破解密码
neommc 发表于 2026-5-28 09:13
官方合并比较难, 老毛子比较独的
比如, 这个项目也好久了, 一直就独立走
https://github.com/mcmilk/7-Zip-zstd
skyfxf 发表于 2026-5-28 09:17
那这种加密的  普通解压软件可以解压吗    7-zip  和  winrar
andyle 发表于 2026-5-28 09:19
跟别人不一样的加密,也解不了啊
null1722 发表于 2026-5-28 09:22
解压怎么办
Rx0 发表于 2026-5-28 09:27
想试试的,看了下,都是源码,不想折腾了
zlqhysy 发表于 2026-5-28 09:37
大神厉害,希望7z采纳
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-14 03:42

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表