🔑 Release WinRAR Keygen

Release WinRAR Keygen
This commit is contained in:
BitCookies 2020-08-09 16:48:33 +08:00 committed by bitcookies
commit 5b4f60d116
59 changed files with 3342 additions and 0 deletions

3
.vs/ProjectSettings.json Normal file
View file

@ -0,0 +1,3 @@
{
"CurrentProjectSetting": "无配置"
}

View file

@ -0,0 +1,7 @@
{
"ExpandedNodes": [
""
],
"SelectedNode": "\\winrar-keygen.sln",
"PreviewInSolutionExplorer": false
}

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

BIN
.vs/winrar-keygen/v16/.suo Normal file

Binary file not shown.

Binary file not shown.

324
BigInteger.hpp Normal file
View file

@ -0,0 +1,324 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <gmp.h>
#include <vector>
#include <string>
#include <type_traits>
#include <stdexcept>
class BigInteger {
private:
mpz_t _Value;
public:
BigInteger() noexcept {
mpz_init(_Value);
}
template<typename __IntegerType>
BigInteger(__IntegerType SmallInteger) noexcept {
// __IntegerType must be a integer type, i.e. char, int, unsigned long...
static_assert(std::is_integral<__IntegerType>::value);
if constexpr (std::is_signed<__IntegerType>::value) {
mpz_init_set_sx(_Value, SmallInteger);
} else {
mpz_init_set_ux(_Value, SmallInteger);
}
}
BigInteger(bool IsNegative, const void* lpBuffer, size_t cbBuffer, bool UseLittleEndian) noexcept {
mpz_init(_Value);
mpz_import(_Value, cbBuffer, UseLittleEndian ? -1 : 1, sizeof(unsigned char), 0, 0, lpBuffer);
if (IsNegative)
mpz_neg(_Value, _Value);
}
BigInteger(bool IsNegative, const std::vector<uint8_t>& Buffer, bool UseLittleEndian) noexcept {
mpz_init(_Value);
mpz_import(_Value, Buffer.size(), UseLittleEndian ? -1 : 1, sizeof(unsigned char), 0, 0, Buffer.data());
if (IsNegative)
mpz_neg(_Value, _Value);
}
BigInteger(const char* lpszValue) noexcept {
mpz_init_set_str(_Value, lpszValue, 0);
}
BigInteger(const std::string& szValue) noexcept {
mpz_init_set_str(_Value, szValue.c_str(), 0);
}
BigInteger(const BigInteger& Other) noexcept {
mpz_init(_Value);
mpz_set(_Value, Other._Value);
}
BigInteger(BigInteger&& Other) noexcept {
mpz_init(_Value);
mpz_swap(_Value, Other._Value);
}
BigInteger& operator=(const BigInteger& Other) noexcept {
if (this != &Other) {
mpz_set(_Value, Other._Value);
}
return *this;
}
BigInteger& operator=(BigInteger&& Other) noexcept {
if (this != &Other) {
mpz_swap(_Value, Other._Value);
mpz_clear(Other._Value);
}
return *this;
}
template<typename __IntegerType>
BigInteger& operator=(__IntegerType SmallInteger) noexcept {
// __IntegerType must be a integer type, i.e. char, int, unsigned long...
static_assert(std::is_integral<__IntegerType>::value);
if constexpr (std::is_signed<__IntegerType>::value) {
mpz_set_sx(_Value, SmallInteger);
} else {
mpz_set_ux(_Value, SmallInteger);
}
return *this;
}
BigInteger& operator=(const char* lpszValue) noexcept {
mpz_init_set_str(_Value, lpszValue, 0);
return *this;
}
bool operator==(const BigInteger& Other) const noexcept {
return mpz_cmp(_Value, Other._Value) == 0;
}
bool operator!=(const BigInteger& Other) const noexcept {
return mpz_cmp(_Value, Other._Value) != 0;
}
bool operator<(const BigInteger& Other) const noexcept {
return mpz_cmp(_Value, Other._Value) < 0;
}
bool operator<=(const BigInteger& Other) const noexcept {
auto d = mpz_cmp(_Value, Other._Value);
return d < 0 || d == 0;
}
bool operator>(const BigInteger& Other) const noexcept {
return mpz_cmp(_Value, Other._Value) > 0;
}
bool operator>=(const BigInteger& Other) const noexcept {
auto d = mpz_cmp(_Value, Other._Value);
return d > 0 || d == 0;
}
BigInteger operator-() const noexcept {
BigInteger Result;
mpz_neg(Result._Value, _Value);
return Result;
}
BigInteger operator+(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_add(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator+=(const BigInteger& Other) noexcept {
mpz_add(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator-(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_sub(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator-=(const BigInteger& Other) noexcept {
mpz_sub(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator*(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_mul(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator*=(const BigInteger& Other) noexcept {
mpz_mul(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator/(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_fdiv_q(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator/=(const BigInteger& Other) noexcept {
mpz_fdiv_q(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator%(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_fdiv_r(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator%=(const BigInteger& Other) noexcept {
mpz_fdiv_r(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator~() const noexcept {
BigInteger Result;
mpz_com(Result._Value, _Value);
return Result;
}
BigInteger operator&(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_and(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator&=(const BigInteger& Other) noexcept {
mpz_and(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator|(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_ior(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator|=(const BigInteger& Other) noexcept {
mpz_ior(_Value, _Value, Other._Value);
return *this;
}
BigInteger operator^(const BigInteger& Other) const noexcept {
BigInteger Result;
mpz_xor(Result._Value, _Value, Other._Value);
return Result;
}
BigInteger& operator^=(const BigInteger& Other) noexcept {
mpz_xor(_Value, _Value, Other._Value);
return *this;
}
BigInteger& operator++() noexcept {
mpz_add_ui(_Value, _Value, 1);
return *this;
}
BigInteger operator++(int) noexcept {
BigInteger Result(*this);
mpz_add_ui(_Value, _Value, 1);
return Result;
}
BigInteger& operator--() noexcept {
mpz_sub_ui(_Value, _Value, 1);
return *this;
}
BigInteger operator--(int) noexcept {
BigInteger Result(*this);
mpz_sub_ui(_Value, _Value, 1);
return Result;
}
bool IsZero() const noexcept {
return mpz_sgn(_Value) == 0;
}
bool IsPositive() const noexcept {
return mpz_sgn(_Value) > 0;
}
bool IsNegative() const noexcept {
return mpz_sgn(_Value) < 0;
}
bool IsOne() const noexcept {
return mpz_cmp_si(_Value, 1) == 0;
}
BigInteger& Load(bool IsNegative, const void* lpBuffer, size_t cbBuffer, bool UseLittleEndian) noexcept {
mpz_import(_Value, cbBuffer, UseLittleEndian ? -1 : 1, sizeof(uint8_t), 0, 0, lpBuffer);
if (IsNegative)
mpz_neg(_Value, _Value);
return *this;
}
BigInteger& Load(bool IsNegative, const std::vector<uint8_t> Buffer, bool UseLittleEndian) noexcept {
mpz_import(_Value, Buffer.size(), UseLittleEndian ? -1 : 1, sizeof(uint8_t), 0, 0, Buffer.data());
if (IsNegative)
mpz_neg(_Value, _Value);
return *this;
}
void DumpAbs(void* lpBuffer, size_t cbBuffer, bool UseLittleEndian) const {
size_t bit_size = mpz_sizeinbase(_Value, 2);
size_t storage_size = (bit_size + 7) / 8;
if (cbBuffer >= storage_size) {
size_t bytes_written;
mpz_export(lpBuffer, &bytes_written, UseLittleEndian ? -1 : 1, sizeof(uint8_t), 0, 0, _Value);
memset(reinterpret_cast<unsigned char*>(lpBuffer) + bytes_written, 0, cbBuffer - bytes_written);
} else {
throw std::length_error("Insufficient buffer.");
}
}
std::vector<uint8_t> DumpAbs(bool UseLittleEndian) const noexcept {
size_t bit_size = mpz_sizeinbase(_Value, 2);
size_t storage_size = (bit_size + 7) / 8;
std::vector<uint8_t> bytes(storage_size);
mpz_export(bytes.data(), nullptr, UseLittleEndian ? -1 : 1, sizeof(uint8_t), 0, 0, _Value);
return bytes;
}
size_t BitLength() const noexcept {
return mpz_sizeinbase(_Value, 2);
}
bool TestBit(size_t i) const noexcept {
return mpz_tstbit(_Value, i) != 0;
}
void SetBit(size_t i) noexcept {
mpz_setbit(_Value, i);
}
std::string ToString(size_t Base, bool LowerCase) const {
if (2 <= Base && Base <= 10 + 26) {
int base = LowerCase ? static_cast<int>(Base) : -static_cast<int>(Base);
std::string s(mpz_sizeinbase(_Value, base) + 2, '\x00');
mpz_get_str(s.data(), base, _Value);
while (s.back() == '\x00') {
s.pop_back();
}
return s;
} else {
throw std::invalid_argument("Invalid base value.");
}
}
};

314
EllipticCurveGF2m.hpp Normal file
View file

@ -0,0 +1,314 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdexcept>
#include <algorithm>
#include "BigInteger.hpp"
template<typename __FieldType>
class EllipticCurveGF2m {
private:
// y^2 + xy = x^3 + Ax^2 + B
__FieldType _A;
__FieldType _B;
void _VerifyParameters() const {
if (_B.IsZero()) {
throw std::invalid_argument("B cannot be zero.");
}
}
public:
class Point {
friend EllipticCurveGF2m<__FieldType>;
private:
const EllipticCurveGF2m<__FieldType>& _Curve;
__FieldType _X;
__FieldType _Y;
void _VerifyParameters() const {
auto Left = _Y.SquareValue() + _X * _Y;
auto Right = (_X + _Curve._A) * _X.SquareValue() + _Curve._B;
if (Left != Right) {
throw std::invalid_argument("New point is not on the curve specified.");
}
}
public:
Point(const EllipticCurveGF2m<__FieldType>& Curve) noexcept :
_Curve(Curve) {}
Point(const EllipticCurveGF2m<__FieldType>& Curve, const void* pbX, size_t cbX, const void* pbY, size_t cbY) :
_Curve(Curve),
_X(pbX, cbX),
_Y(pbY, cbY)
{
_VerifyParameters();
}
Point(const EllipticCurveGF2m<__FieldType>& Curve, const __FieldType& X, const __FieldType& Y) :
_Curve(Curve), _X(X), _Y(Y)
{
_VerifyParameters();
}
Point operator-() const noexcept {
return Point(_X, _X + _Y);
}
Point& operator=(const Point& Other) {
if (&_Curve == &Other._Curve || _Curve == Other._Curve) {
_X = Other._X;
_Y = Other._Y;
return *this;
} else {
throw std::invalid_argument("Not on the same curve.");
}
}
bool operator==(const Point& Other) const noexcept {
if (&_Curve == &Other._Curve || _Curve == Other._Curve) {
return _X == Other._X && _Y == Other._Y;
} else {
return false;
}
}
bool operator!=(const Point& Other) const noexcept {
if (&_Curve == &Other._Curve || _Curve == Other._Curve) {
return _X != Other._X || _Y != Other._Y;
} else {
return true;
}
}
const __FieldType& GetX() const noexcept {
return _X;
}
const __FieldType& GetY() const noexcept {
return _Y;
}
bool IsAtInfinity() const noexcept {
return _X.IsZero() && _Y.IsZero();
}
Point& Double() noexcept {
if (IsAtInfinity() == false) {
auto m = _Y / _X + _X;
// NewX = m ^ 2 + m + a
__FieldType NewX = m.SquareValue();
NewX += m;
NewX += _Curve._A;
// NewY = X ^ 2 + (m + 1) * NewX
_Y = m.AddOne();
_Y *= NewX;
_Y += _X.Square();
_X = NewX;
}
return *this;
}
Point ValueOfDouble() const noexcept {
Point Result(_Curve);
if (IsAtInfinity() == false) {
// m = X + Y / X
auto m = _Y / _X + _X;
// NewX = m ^ 2 + m + a
Result._X = m.SquareValue();
Result._X += m;
Result._X += _Curve._A;
// NewY = X ^ 2 + (m + 1) * NewX
Result._Y = m.AddOne();
Result._Y *= Result._X;
Result._Y += _X.SquareValue();
}
return Result;
}
Point operator+(const Point& Other) const {
if (&_Curve == &Other._Curve || _Curve == Other._Curve) {
if (IsAtInfinity()) {
return Other;
} else {
if (this == &Other || _X == Other._X) {
return ValueOfDouble();
} else {
Point Result(_Curve);
// m = (Y0 + Y1) / (X0 + X1)
auto m = (_Y + Other._Y) / (_X + Other._X);
// NewX = m ^ 2 + m + X0 + X1 + a
Result._X = m.SquareValue();
Result._X += m;
Result._X += _X;
Result._X += Other._X;
Result._X += _Curve._A;
// NewY = m * (X0 + NewX) + NewX + Y0
Result._Y = _X + Result._X;
Result._Y *= m;
Result._Y += Result._X;
Result._Y += _Y;
return Result;
}
}
} else {
throw std::invalid_argument("Not on the same curve.");
}
}
Point& operator+=(const Point& Other) {
if (&_Curve == &Other._Curve || _Curve == Other._Curve) {
if (IsAtInfinity()) {
_X = Other._X;
_Y = Other._Y;
} else {
if (this == &Other || _X == Other._X) {
Double();
} else {
Point Result(_Curve);
// m = (Y0 + Y1) / (X0 + X1)
auto m = (_Y + Other._Y) / (_X + Other._X);
// NewX = m ^ 2 + m + X0 + X1 + a
__FieldType NewX = m.SquareValue();
NewX += m;
NewX += _X;
NewX += Other._X;
NewX += _Curve._A;
// NewY = m * (X0 + NewX) + NewX + Y0
_X += NewX;
_X *= m;
_X += NewX;
_Y += _X;
_X = NewX;
}
}
return *this;
} else {
throw std::invalid_argument("Not on the same curve.");
}
}
Point operator-(const Point& Other) const {
Point Result = -Other;
Result += *this;
return Result;
}
Point& operator-=(const Point& Other) {
return *this += -Other;
}
Point operator*(const BigInteger N) const noexcept {
Point Result(_Curve);
Point temp(*this);
size_t bit_length = N.BitLength();
for (size_t i = 0; i < bit_length; ++i) {
if (N.TestBit(i) == true)
Result += temp;
temp.Double();
}
return Result;
}
Point operator*=(const BigInteger N) noexcept {
Point Result(_Curve);
size_t bit_length = N.BitLength();
for (size_t i = 0; i < bit_length; ++i) {
if (N.TestBit(i) == true)
Result += *this;
Double();
}
*this = Result;
}
// SEC 1: Elliptic Curve Cryptography
// 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion
std::vector<uint8_t> Dump() const noexcept {
if (IsAtInfinity()) {
std::vector<uint8_t> bytes = { 0x00 };
return bytes;
} else {
std::vector<uint8_t> bytes = { 0x04 };
std::vector<uint8_t> xbytes = _X.Dump();
std::vector<uint8_t> ybytes = _Y.Dump();
std::reverse(xbytes.begin(), xbytes.end()); // to big endian
std::reverse(ybytes.begin(), ybytes.end()); // to big endian
bytes.insert(bytes.end(), xbytes.begin(), xbytes.end());
bytes.insert(bytes.end(), ybytes.begin(), ybytes.end());
return bytes;
}
}
// SEC 1: Elliptic Curve Cryptography
// 2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion
std::vector<uint8_t> DumpCompressed() const noexcept {
if (IsAtInfinity()) {
std::vector<uint8_t> bytes = { 0x00 };
return bytes;
} else {
std::vector<uint8_t> bytes(1);
std::vector<uint8_t> xbytes = _X.Dump();
std::vector<uint8_t> zbytes = (_Y / _X).Dump();
if (zbytes[0] & 1) {
bytes[0] = 0x03;
} else {
bytes[0] = 0x02;
}
std::reverse(xbytes.begin(), xbytes.end()); // to big endian
bytes.insert(bytes.end(), xbytes.begin(), xbytes.end());
return bytes;
}
}
};
EllipticCurveGF2m(const __FieldType& A, const __FieldType& B) : _A(A), _B(B) {
_VerifyParameters();
}
EllipticCurveGF2m(const void* pbA, size_t cbA, const void* pbB, size_t cbB) : _A(pbA, cbA), _B(pbB, cbB) {
_VerifyParameters();
}
bool operator==(const EllipticCurveGF2m<__FieldType>& Other) const noexcept {
return _A == Other._A && _B == Other._B;
}
bool operator!=(const EllipticCurveGF2m<__FieldType>& Other) const noexcept {
return _A != Other._A || _B != Other._B;
}
Point GetInfinityPoint() const noexcept {
return Point(*this);
}
Point GetPoint(const __FieldType& X, const __FieldType& Y) const {
return Point(*this, X, Y);
}
Point GetPoint(const void* pbX, size_t cbX, const void* pbY, size_t cbY) const {
return Point(*this, pbX, cbX, pbY, cbY);
}
};

226
GaloisField.hpp Normal file
View file

@ -0,0 +1,226 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include <type_traits>
struct GaloisFieldInitByZero {};
struct GaloisFieldInitByOne {};
struct GaloisFieldInitByElement {};
struct GaloisFieldInitByDump {};
template<typename __FieldTraits>
class GaloisField {
public:
static constexpr size_t BitSizeValue = __FieldTraits::BitSizeValue;
static constexpr size_t DumpSizeValue = __FieldTraits::DumpSizeValue;
private:
static_assert(std::is_pod<typename __FieldTraits::ElementType>::value == true);
typename __FieldTraits::ElementType _Val;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 26495) // disable uninitialized warning
#endif
struct NoInitialization {};
GaloisField(NoInitialization) noexcept {};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
public:
GaloisField() noexcept {
__FieldTraits::SetZero(_Val);
}
GaloisField(GaloisFieldInitByZero) noexcept {
__FieldTraits::SetZero(_Val);
}
GaloisField(GaloisFieldInitByOne) noexcept {
__FieldTraits::SetOne(_Val);
}
GaloisField(GaloisFieldInitByElement, const typename __FieldTraits::ElementType& Element) {
__FieldTraits::Verify(Element);
_Val = Element;
}
GaloisField(GaloisFieldInitByDump, const void* pbBuffer, size_t cbBuffer) {
__FieldTraits::Load(_Val, pbBuffer, cbBuffer);
}
template<typename __Dummy = std::enable_if<BitSizeValue <= sizeof(uintptr_t) * 8>::type>
GaloisField(GaloisFieldInitByDump, uintptr_t SerializedValue) {
__FieldTraits::Load(_Val, SerializedValue);
}
GaloisField<__FieldTraits>& operator=(const typename __FieldTraits::ElementType& Element) {
__FieldTraits::Verify(Element);
_Val = Element;
return *this;
}
template<typename __Dummy = std::enable_if<BitSizeValue <= sizeof(uintptr_t) * 8>::type>
GaloisField<__FieldTraits>& operator=(uintptr_t SerializedValue) {
__FieldTraits::Load(_Val, SerializedValue);
return *this;
}
bool IsZero() const noexcept {
return __FieldTraits::IsZero(_Val);
}
bool IsOne() const noexcept {
return __FieldTraits::IsOne(_Val);
}
bool operator==(const GaloisField<__FieldTraits>& Other) const noexcept {
return __FieldTraits::IsEqual(_Val, Other._Val);
}
bool operator!=(const GaloisField<__FieldTraits>& Other) const noexcept {
return __FieldTraits::IsEqual(_Val, Other._Val) == false;
}
GaloisField<__FieldTraits> operator+(const GaloisField<__FieldTraits>& Other) const noexcept {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::Add(Result._Val, _Val, Other._Val);
return Result;
}
GaloisField<__FieldTraits>& operator+=(const GaloisField<__FieldTraits>& Other) noexcept {
__FieldTraits::AddAssign(_Val, Other._Val);
return *this;
}
GaloisField<__FieldTraits> operator-(const GaloisField<__FieldTraits>& Other) const noexcept {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::Substract(Result._Val, _Val, Other._Val);
return Result;
}
GaloisField<__FieldTraits>& operator-=(const GaloisField<__FieldTraits>& Other) noexcept {
__FieldTraits::SubstractAssign(_Val, Other._Val);
return *this;
}
GaloisField<__FieldTraits> operator*(const GaloisField<__FieldTraits>& Other) const noexcept {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::Multiply(Result._Val, _Val, Other._Val);
return Result;
}
GaloisField<__FieldTraits>& operator*=(const GaloisField<__FieldTraits>& Other) noexcept {
__FieldTraits::MultiplyAssign(_Val, Other._Val);
return *this;
}
GaloisField<__FieldTraits> operator/(const GaloisField<__FieldTraits>& Other) const {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::Divide(Result._Val, _Val, Other._Val);
return Result;
}
GaloisField<__FieldTraits>& operator/=(const GaloisField<__FieldTraits>& Other) {
__FieldTraits::DivideAssign(_Val, Other._Val);
return *this;
}
GaloisField<__FieldTraits>& operator++() noexcept { // prefix ++
__FieldTraits::AddOneAssign(_Val);
return *this;
}
GaloisField<__FieldTraits> operator++(int) noexcept { // postfix ++
GaloisField<__FieldTraits> Prev(*this);
__FieldTraits::AddOneAssign(_Val);
return Prev;
}
GaloisField<__FieldTraits>& operator--() noexcept { // prefix --
__FieldTraits::SubstractOneAssign(_Val);
return *this;
}
GaloisField<__FieldTraits> operator--(int) noexcept { // postfix --
GaloisField<__FieldTraits> Prev(*this);
__FieldTraits::SubstractOneAssign(_Val);
return Prev;
}
GaloisField<__FieldTraits>& Inverse() {
__FieldTraits::InverseAssign(_Val);
return *this;
}
GaloisField<__FieldTraits> InverseValue() const {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::Inverse(Result, _Val);
return Result;
}
GaloisField<__FieldTraits>& AddOne() noexcept {
__FieldTraits::AddOneAssign(_Val);
return *this;
}
GaloisField<__FieldTraits> AddOneValue() const noexcept {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::AddOne(Result._Val, _Val);
return Result;
}
GaloisField<__FieldTraits>& SubstractOne() noexcept {
__FieldTraits::SubstractOneAssign(_Val);
return *this;
}
GaloisField<__FieldTraits> SubstractOneValue() const noexcept {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::SubstractOne(Result._Val, _Val);
return Result;
}
GaloisField<__FieldTraits>& Square() noexcept {
__FieldTraits::SquareAssign(_Val);
return *this;
}
GaloisField<__FieldTraits> SquareValue() const noexcept {
GaloisField<__FieldTraits> Result(NoInitialization{});
__FieldTraits::Square(Result._Val, _Val);
return Result;
}
template<typename __Dummy = std::enable_if<BitSizeValue <= sizeof(uintptr_t) * 8>::type>
uintptr_t Dump() const noexcept {
return __FieldTraits::Dump(_Val);
}
size_t Dump(void* lpBuffer, size_t cbBuffer) const {
return __FieldTraits::Dump(_Val, lpBuffer, cbBuffer);
}
std::vector<uint8_t> Dump() const noexcept {
return __FieldTraits::Dump(_Val);
}
template<typename __Dummy = std::enable_if<BitSizeValue <= sizeof(uintptr_t) * 8>::type>
GaloisField<__FieldTraits>& Load(uintptr_t SerializedValue) {
__FieldTraits::Load(_Val, SerializedValue);
return *this;
}
GaloisField<__FieldTraits>& Load(const void* lpBuffer, size_t cbBuffer) {
__FieldTraits::Load(_Val, lpBuffer, cbBuffer);
return *this;
}
GaloisField<__FieldTraits>& Load(const std::vector<uint8_t>& Buffer) {
__FieldTraits::Load(_Val, Buffer);
return *this;
}
};

62
Hasher.hpp Normal file
View file

@ -0,0 +1,62 @@
#pragma once
#include <utility>
template<typename __HashTraits>
class Hasher {
public:
static constexpr size_t BlockSizeValue = __HashTraits::BlockSize;
static constexpr size_t DigestSizeValue = __HashTraits::DigestSize;
using DigestType = typename __HashTraits::DigestType;
private:
using ContextType = typename __HashTraits::ContextType;
ContextType _Ctx;
public:
Hasher(__HashTraits) :
_Ctx(__HashTraits::ContextCreate()) {}
template<typename... __Ts>
Hasher(__HashTraits, __Ts&&... Args) :
_Ctx(__HashTraits::ContextCreate(std::forward<__Ts>(Args)...)) {}
Hasher(const Hasher<__HashTraits>& Other) :
_Ctx(__HashTraits::ContextCopy(Other._Ctx)) {}
Hasher(Hasher<__HashTraits>&& Other) noexcept :
_Ctx(std::move(Other._Ctx)) {}
Hasher<__HashTraits>& operator=(const Hasher<__HashTraits>& Other) {
ContextType t = __HashTraits::ContextCopy(Other._Ctx);
__HashTraits::ContextDestroy(_Ctx);
_Ctx = std::move(t);
return *this;
}
Hasher<__HashTraits>& operator=(Hasher<__HashTraits>&& Other) noexcept {
_Ctx = std::move(Other._Ctx);
return *this;
}
constexpr size_t BlockSize() const noexcept {
return BlockSizeValue;
}
constexpr size_t DigestSize() const noexcept {
return DigestSizeValue;
}
void Update(const void* lpBuffer, size_t cbBuffer) noexcept {
__HashTraits::ContextUpdate(_Ctx, lpBuffer, cbBuffer);
}
DigestType Evaluate() const noexcept {
DigestType Digest;
__HashTraits::ContextEvaluate(_Ctx, Digest);
return Digest;
}
~Hasher() {
__HashTraits::ContextDestroy(_Ctx);
}
};

198
HasherCrc32Traits.hpp Normal file
View file

@ -0,0 +1,198 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
template<uint32_t __Polynomial>
struct HasherCrc32Traits {
static constexpr size_t BlockSize = 0;
static constexpr size_t DigestSize = 32 / 8;
using DigestType = uint32_t;
using LookupTableType = uint32_t[256];
struct ContextType {
uint32_t Value;
ContextType() noexcept :
Value(0) {}
ContextType(uint32_t InitialValue) noexcept :
Value(InitialValue) {}
ContextType(const ContextType& Other) noexcept = default;
ContextType(ContextType&& Other) noexcept : Value(Other.Value) {
Other.Value = 0;
}
ContextType& operator=(const ContextType& Other) noexcept = default;
ContextType& operator=(ContextType&& Other) noexcept {
Value = Other.Value;
Other.Value = 0;
return *this;
}
};
static const LookupTableType& InitializeLookupTable() noexcept {
static LookupTableType LookupTable = {};
if (LookupTable[1] == 0) {
for (unsigned i = 0; i < 256; ++i) {
uint32_t result = i;
for (unsigned j = 0; j < 8; ++j) {
if (result % 2) {
result /= 2;
result ^= __Polynomial;
} else {
result /= 2;
}
}
LookupTable[i] = result;
}
}
return LookupTable;
}
static inline const LookupTableType& LookupTable = InitializeLookupTable();
static inline ContextType ContextCreate() noexcept {
ContextType Ctx;
return Ctx;
}
static inline ContextType ContextCreate(const void* lpBuffer, size_t cbBuffer) noexcept {
ContextType Ctx;
ContextUpdate(Ctx, lpBuffer, cbBuffer);
return Ctx;
}
static inline ContextType ContextCreate(uint32_t InitialValue) noexcept {
ContextType Ctx(InitialValue);
return Ctx;
}
static inline ContextType ContextCreate(uint32_t InitialValue, const void* lpBuffer, size_t cbBuffer) noexcept {
ContextType Ctx;
ContextUpdate(Ctx, lpBuffer, cbBuffer);
return Ctx;
}
static inline ContextType ContextCopy(const ContextType& Ctx) noexcept {
return Ctx;
}
static inline void ContextUpdate(ContextType& Ctx, const void* lpBuffer, size_t cbBuffer) noexcept {
auto pbBuffer = reinterpret_cast<const uint8_t*>(lpBuffer);
Ctx.Value = ~Ctx.Value;
for (size_t i = 0; i < cbBuffer; ++i) {
Ctx.Value = (Ctx.Value >> 8) ^ LookupTable[static_cast<uint8_t>(Ctx.Value) ^ pbBuffer[i]];
}
Ctx.Value = ~Ctx.Value;
}
static inline void ContextEvaluate(const ContextType& Ctx, DigestType& Digest) noexcept {
Digest = Ctx.Value;
}
static inline void ContextDestroy(ContextType& Ctx) noexcept {
Ctx.Value = 0;
}
};
#ifdef _MSC_VER
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#pragma comment(lib, "ntdll")
// available on WindowsXP and above
NTSYSAPI
DWORD
NTAPI
RtlComputeCrc32(
_In_ DWORD InitialCrc,
_In_reads_bytes_(Size) const void* Buffer,
_In_ size_t Size
);
#ifdef __cplusplus
}
#endif
template<>
struct HasherCrc32Traits<0xEDB88320> {
static constexpr size_t BlockSize = 0;
static constexpr size_t DigestSize = 32 / 8;
using DigestType = uint32_t;
struct ContextType {
uint32_t Value;
ContextType() noexcept :
Value(0) {}
ContextType(uint32_t InitialValue) noexcept :
Value(InitialValue) {}
ContextType(const ContextType& Other) noexcept = default;
ContextType(ContextType&& Other) noexcept : Value(Other.Value) {
Other.Value = 0;
}
ContextType& operator=(const ContextType& Other) noexcept = default;
ContextType& operator=(ContextType&& Other) noexcept {
Value = Other.Value;
Other.Value = 0;
return *this;
}
};
static inline ContextType ContextCreate() noexcept {
ContextType Ctx;
return Ctx;
}
static inline ContextType ContextCreate(const void* lpBuffer, size_t cbBuffer) noexcept {
ContextType Ctx;
ContextUpdate(Ctx, lpBuffer, cbBuffer);
return Ctx;
}
static inline ContextType ContextCreate(uint32_t InitialValue) noexcept {
ContextType Ctx(InitialValue);
return Ctx;
}
static inline ContextType ContextCreate(uint32_t InitialValue, const void* lpBuffer, size_t cbBuffer) noexcept {
ContextType Ctx;
ContextUpdate(Ctx, lpBuffer, cbBuffer);
return Ctx;
}
static inline ContextType ContextCopy(const ContextType& Ctx) noexcept {
return Ctx;
}
static inline void ContextUpdate(ContextType& Ctx, const void* lpBuffer, size_t cbBuffer) noexcept {
Ctx.Value = RtlComputeCrc32(Ctx.Value, lpBuffer, cbBuffer);
}
static inline void ContextEvaluate(const ContextType& Ctx, DigestType& Digest) noexcept {
Digest = Ctx.Value;
}
static inline void ContextDestroy(ContextType& Ctx) noexcept {
Ctx.Value = 0;
}
};
#endif // #ifdef _MSC_VER

153
HasherSha1Traits.hpp Normal file
View file

@ -0,0 +1,153 @@
#pragma once
#ifdef _MSC_VER
#include <windows.h>
#include <wincrypt.h>
#include <system_error>
struct HasherSha1Traits {
public:
static constexpr size_t BlockSize = 512 / 8;
static constexpr size_t DigestSize = 160 / 8;
struct DigestType {
BYTE Bytes[DigestSize];
};
struct ContextType {
HCRYPTHASH hHash;
ContextType() noexcept :
hHash(NULL) {}
ContextType(HCRYPTHASH HashHandle) noexcept :
hHash(HashHandle) {}
ContextType(const ContextType& Other) noexcept = default;
ContextType(ContextType&& Other) noexcept : hHash(Other.hHash) {
Other.hHash = NULL;
}
ContextType& operator=(const ContextType& Other) noexcept = default;
ContextType& operator=(ContextType&& Other) noexcept {
hHash = Other.hHash;
Other.hHash = NULL;
return *this;
}
};
private:
static inline struct ContextProvider {
HCRYPTPROV Handle;
~ContextProvider() {
if (Handle) {
CryptReleaseContext(Handle, 0);
Handle = NULL;
}
}
} CryptProvider;
public:
static inline ContextType ContextCreate() {
ContextType Ctx;
if (CryptProvider.Handle == NULL) {
if (!CryptAcquireContext(&CryptProvider.Handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) {
auto err = GetLastError();
if (err == NTE_BAD_KEYSET) {
if (!CryptAcquireContext(&CryptProvider.Handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET)) {
err = GetLastError();
throw std::system_error(err, std::system_category());
}
} else {
throw std::system_error(err, std::system_category());
}
}
}
if (!CryptCreateHash(CryptProvider.Handle, CALG_SHA1, NULL, 0, &Ctx.hHash)) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
return Ctx;
}
static inline ContextType ContextCreate(const void* lpBuffer, size_t cbBuffer) {
ContextType Ctx;
if (CryptProvider.Handle == NULL) {
if (!CryptAcquireContext(&CryptProvider.Handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) {
auto err = GetLastError();
if (err == NTE_BAD_KEYSET) {
if (!CryptAcquireContext(&CryptProvider.Handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET)) {
err = GetLastError();
throw std::system_error(err, std::system_category());
}
} else {
throw std::system_error(err, std::system_category());
}
}
}
if (!CryptCreateHash(CryptProvider.Handle, CALG_SHA1, NULL, 0, &Ctx.hHash)) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
ContextUpdate(Ctx, lpBuffer, cbBuffer);
return Ctx;
}
static inline ContextType ContextCopy(const ContextType& Ctx) {
ContextType NewCtx;
if (!CryptDuplicateHash(Ctx.hHash, NULL, 0, &NewCtx.hHash)) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
return NewCtx;
}
static inline void ContextUpdate(ContextType& Ctx, const void* lpBuffer, size_t cbBuffer) {
if constexpr (sizeof(size_t) <= sizeof(DWORD)) {
if (!CryptHashData(Ctx.hHash, reinterpret_cast<const BYTE*>(lpBuffer), static_cast<DWORD>(cbBuffer), 0)) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
} else {
size_t BytesRead = 0;
DWORD BytesToRead = cbBuffer - BytesRead > MAXDWORD ? MAXDWORD : static_cast<DWORD>(cbBuffer - BytesRead);
do {
if (!CryptHashData(Ctx.hHash, reinterpret_cast<const BYTE*>(lpBuffer) + BytesRead, BytesToRead, 0)) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
BytesRead += BytesToRead;
BytesToRead = cbBuffer - BytesRead > MAXDWORD ? MAXDWORD : static_cast<DWORD>(cbBuffer - BytesRead);
} while (BytesToRead);
}
}
static inline void ContextEvaluate(const ContextType& Ctx, DigestType& Digest) {
DWORD SizeOfDigest = sizeof(Digest.Bytes);
if (!CryptGetHashParam(Ctx.hHash, HP_HASHVAL, Digest.Bytes, &SizeOfDigest, 0)) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
static inline void ContextDestroy(ContextType& Ctx) noexcept {
if (Ctx.hHash) {
CryptDestroyHash(Ctx.hHash);
Ctx.hHash = NULL;
}
}
};
#endif

321
README.HOW_DOES_IT_WORK.md Normal file
View file

@ -0,0 +1,321 @@
[GF2-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BGF%7D%282%29
[GF2p15-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BGF%7D%282%5E%7B15%7D%29
[GF2p15p17-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29
[A-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20A
[B-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20B
[D-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20D
[G-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20G
[M-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20M
[P-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20P
[h-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20h
[k-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20k
[l-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20l
[n-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20n
[r-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20r
[s-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20s
[T-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20T
[UU-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20U
[LL-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20L
[Rnd-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Rnd
[Temp-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Temp
[UID-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20UID
[Data-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data
[Data0-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E0
[Data1-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E1
[Data2-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E2
[Data3-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E3
# How is "rarreg.key" generated?
WinRAR uses an ECC-based signature algorithm to generate `rarreg.key`. The algorithm it used is a varient of Chinese SM2 digital signature algorithm. Different to many standard ECDSAs, the curve that WinRAR selected is a curve over composite field ![GF2p15p17-inlined].
## 1. Composite field ![GF2p15p17-inlined]
Elements in ground field ![GF2p15-inlined] are represented with standard basis, i.e. polynomial basis. The irreducible polynomial is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?P%28%5Calpha%29%3D%5Calpha%5E%7B15%7D&plus;%5Calpha&plus;1")
</p>
where each coefficients is in ![GF2-inlined]. If we use
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B_1%3D%5C%7B1%2C%5Calpha%2C%5Calpha%5E2%2C%5Cldots%2C%5Calpha%5E%7B14%7D%5C%7D")
</p>
as the standard basis of the ground field, an element ![A-inlined] in ![GF2p15-inlined] can be denoted as
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?A%3D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_i%5Calpha%5Ei%20%5Cquad%20%5Cquad%20%5Cquad%20a_i%5Cin%5Ctextrm%7BGF%7D%282%29")
</p>
---
The irreducible polynomial of composite field ![GF2p15p17-inlined] is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Q%28%5Cbeta%29%3D%5Cbeta%5E%7B17%7D&plus;%5Cbeta%5E3&plus;1")
</p>
where each coefficients is in ![GF2p15-inlined]. If we use
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B_2%3D%5C%7B1%2C%5Cbeta%2C%5Cbeta%5E2%2C%5Cldots%2C%5Cbeta%5E%7B16%7D%5C%7D")
</p>
as the standard basis of the composite field, an element ![B-inlined] in ![GF2p15p17-inlined] can be denoted as
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%28%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Calpha%5Ei%29%5Cbeta%5Ej%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Calpha%5Ei%5Cbeta%5Ej%20%5Cquad%20%5Cquad%20%5Cquad%20a_%7Bj%2Ci%7D%5Cin%5Ctextrm%7BGF%7D%282%29")
</p>
---
For clarity, we use ![D-inlined], which is a 255-bits-long integer to denote an element ![B-inlined] in ![GF2p15p17-inlined]. The map between them is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Calpha%5Ei%5Cbeta%5Ej%20%5Cleftrightarrow%20D%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Ccdot%202%5E%7B15j&plus;i%7D")
</p>
## 2. Elliptic curve over ![GF2p15p17-inlined]
The equation of the elliptic curve that WinRAR uses is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?y%5E2&plus;xy%3Dx%5E3&plus;161%20%5Cquad%20%5Cquad%20%5Cquad%20161%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29")
</p>
The base point ![G-inlined] is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20G%26%3D%28G_x%2CG_y%29%20%5C%5C%20G_x%26%3D%5Ctextrm%7B0x56fdcbc6a27acee0cc2996e0096ae74feb1acf220a2341b898b549440297b8cc%7D%20%5Cquad%20G_x%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%5C%5C%20G_y%26%3D%5Ctextrm%7B0x20da32e8afc90b7cf0e76bde44496b4d0794054e6ea60f388682463132f931a7%7D%20%5Cquad%20G_y%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%20%5Cend%7Baligned%7D")
</p>
whose order ![n-inlined] is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?n%3D%5Ctextrm%7B0x1026dd85081b82314691ced9bbec30547840e4bf72d8b5e0d258442bbcd31%7D%20%5Cquad%20n%5Cin%5Cnolinebreak%5Cmathbb%7BZ%7D")
</p>
## 3. Message hash algorithm
We use
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?M%3Dm_0m_1%20%5Cldots%20m_%7Bl-1%7D%20%5Cquad%20%5Cquad%20m_i%5Cin%5B0%2C%20256%29")
</p>
to denote a message whose length is ![l-inlined]. So the SHA1 value of ![M-inlined] should be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Ctextrm%7BSHA%7D_1%28M%29%3DS_0%7C%7CS_1%7C%7CS_2%7C%7CS_3%7C%7CS_4%20%5Cquad%20%5Cquad%20S_i%5Cin%5B0%2C%202%5E%7B32%7D%29")
</p>
where ![](http://latex.codecogs.com/svg.latex?%5Cinline%20S_0%2CS_1%2CS_2%2CS_3%2CS_4) are 5 state values when SHA1 outputs. Generally speaking, the final SHA1 value should be the join of these 5 state values while each of state values is serialized in big-endian.
However, WinRAR doesn't serialize the 5 state values. Instead, it use a big integer ![h-inlined] as the hash of the input message.
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?h%3D%28%5Csum_%7Bi%3D0%7D%5E%7B4%7DS_i%20%5Ccdot%202%5E%7B32i%7D%29&plus;%5Ctextrm%7B0x1bd10xb4e33c7c0ffd8d43%7D%20%5Ccdot%202%5E%7B32*5%7D")
</p>
## 4. ECC digital signature algorithm
We use ![k-inlined] to denote private key, ![P-inlined] to denote public key. So there must be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?P%3Dk%20%5Ccdot%20G")
</p>
If we use ![h-inlined] to denote the hash of input data, WinRAR use the following algorithm to perform signing:
1. Generate a random big integer ![Rnd-inlined] which satisfies ![](http://latex.codecogs.com/svg.latex?%5Cinline%200%3CRnd%3Cn).
2. Calculate ![r-inlined]
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?r%3D%28%28Rnd%20%5Ccdot%20G%29_x&plus;h%29%5C%20%5C%20Mod%5C%20%5C%20n">
</p>
where ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28Rnd%20%5Ccdot%20G%29_x) means we take X coordinate of ![](http://latex.codecogs.com/svg.latex?%5Cinline%20Rnd%20%5Ccdot%20G) and convert it from ![GF2p15p17-inlined] to a big integer.
If ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r%3D0) or ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r&plus;Rnd%3Dn), go back to step 1.
3. Calculate ![s-inlined]
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?s%3D%28Rnd-kr%29%5C%20%5C%20Mod%5C%20%5C%20n">
</p>
If ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s%3D0), go back to step 1.
4. Output ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r%2Cs%29).
## 5. WinRAR private key generation algorithm
We use
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?T%3Dt_0t_1%20%5Cldots%20t_%7Bl-1%7D%20%5Cquad%20%5Cquad%20t_i%5Cin%5B0%2C256%29">
</p>
to denote input data whose length is ![l-inlined]. WinRAR use it to generate private key ![k-inlined].
1. We use ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_0%2Cg_1%2Cg_2%2Cg_3%2Cg_4%2Cg_5) to denote 6 32-bits-long integer. So there is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?g_j%3D%5Csum_%7Bi%3D0%7D%5E%7B3%7Dg_%7Bj%2Ci%7D%20%5Ccdot%202%5E%7B8i%7D%20%5Cquad%20%5Cquad%20g_%7Bj%2Ci%7D%5Cin%5B0%2C256%29">
</p>
2. Let ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_0%3D0).
3. If ![](http://latex.codecogs.com/svg.latex?%5Cinline%20l%5Cneq%200), we calculate SHA1 value of ![T-inlined]. Then assign SHA1 state value ![](http://latex.codecogs.com/svg.latex?%5Cinline%20S_i) to ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_%7Bi&plus;1%7D):
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20%5Ctextrm%7BSHA%7D_1%28T%29%26%3DS_0%7C%7CS_1%7C%7CS_2%7C%7CS_3%7C%7CS_4%20%5C%5C%20g_1%26%3DS_0%20%5C%5C%20g_2%26%3DS_1%20%5C%5C%20g_3%26%3DS_2%20%5C%5C%20g_4%26%3DS_3%20%5C%5C%20g_5%26%3DS_4%20%5C%5C%20%5Cend%7Baligned%7D">
</p>
Otherwise, when ![](http://latex.codecogs.com/svg.latex?%5Cinline%20l%3D0), we let
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20g_1%26%3D%5Ctextrm%7B0xeb3eb781%7D%20%5C%5C%20g_2%26%3D%5Ctextrm%7B0x50265329%7D%20%5C%5C%20g_3%26%3D%5Ctextrm%7B0xdc5ef4a3%7D%20%5C%5C%20g_4%26%3D%5Ctextrm%7B0x6847b9d5%7D%20%5C%5C%20g_5%26%3D%5Ctextrm%7B0xcde43b4c%7D%20%5C%5C%20%5Cend%7Baligned%7D">
</p>
4. Regard ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_0) as counter, add itself by 1.
Calculate SHA1:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Ctextrm%7BSHA%7D_1%28g_%7B0%2C0%7D%7C%7Cg_%7B0%2C1%7D%7C%7Cg_%7B0%2C2%7D%7C%7Cg_%7B0%2C3%7D%7C%7Cg_%7B1%2C0%7D%7C%7Cg_%7B1%2C1%7D%7C%7C%5Cldots%7C%7Cg_%7B5%2C0%7D%7C%7Cg_%7B5%2C1%7D%7C%7Cg_%7B5%2C2%7D%7C%7Cg_%7B5%2C3%7D%29%3DS_0%7C%7CS_1%7C%7CS_2%7C%7CS_3%7C%7CS_4">
</p>
We takes the lowest 16 bits of ![](http://latex.codecogs.com/svg.latex?%5Cinline%20S_0) and donote it as ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_%7Bg_0%7D).
5. Repeat step 4 again with 14 times.
6. After that, we will get ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_1%2Ck_2%2Ck_3%2C%5Cldots%2Ck_%7B15%7D). Then output private key
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?k%3D%5Csum_%7Bi%3D1%7D%5E%7B15%7Dk_i%20%5Ccdot%202%5E%7B16i%7D">
</p>
## 6. The private key and public key of WinRAR
Private key ![k-inlined] is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?k%3D%5Ctextrm%7B0x59fe6abcca90bdb95f0105271fa85fb9f11f467450c1ae9044b7fd61d65e%7D%20%5Cquad%20%5Cquad%20k%5Cin%5Cnolinebreak%5Cmathbb%7BZ%7D">
</p>
This private key is generated by the algorithm describled in section 5 where the length of data ![T-inlined] is zero.
Public key ![P-inlined] is
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20P%26%3D%28P_x%2CP_y%29%20%5C%5C%20P_x%26%3D%5Ctextrm%7B0x3861220ed9b36c9753df09a159dfb148135d495db3af8373425ee9a28884ba1a%7D%20%5Cquad%20P_x%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%20%5C%5C%20P_y%26%3D%5Ctextrm%7B0x12b64e62db43a56114554b0cbd573379338cea9124c8443c4f50e6c8b013ec20%7D%20%5Cquad%20P_y%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%20%5Cend%7Baligned%7D">
</p>
## 7. Generation of "rarreg.key"
The generation of license file `rarreg.key` requires 2 arguments:
1. Username, an ANSI-encoded string, without null-terminator. Denoted as
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?U%3Du_0u_1%20%5Cldots%20u_%7Bl-1%7D">
</p>
2. License type, an ANSI-encoded string, without null-terminator. Denoted as
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?L%3Dl_0l_1%20%5Cldots%20l_%7Bl-1%7D">
</p>
The following is the algorithm to generate `rarreg.key`.
1. Use the algorithm describled in section 5, with argument ![UU-inlined], to generate private key ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_U) and public key ![](http://latex.codecogs.com/svg.latex?%5Cinline%20P_U). Then output hexlified public key string with SM2 compressed public key format. The hexlified public key is denoted as ![Temp-inlined].
The length of ![Temp-inlined] should be 64. If less, pad with `'0'` until the length is 64.
2. Let ![Data3-inlined] be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Data%5E3%3D%5Ctexttt%7B%2260%22%7D%7C%7CTemp_0%7C%7CTemp_1%7C%7C%5Cldots%7C%7CTemp_%7B47%7D">
</p>
3. Use the algorithm describled in section 5, with argument ![Data3-inlined], to generate private key ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_%7BData%5E3%7D) and public key ![](http://latex.codecogs.com/svg.latex?%5Cinline%20P_%7BData%5E3%7D). Then output hexlified public key string with SM2 compressed public key format. The hexlified public key is denoted as ![Data0-inlined].
The length of ![Data0-inlined] should be 64. If less, pad with `'0'` until the length is 64.
4. Let ![UID-inlined] be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?UID%3DTemp_%7B48%7D%7C%7CTemp_%7B49%7D%7C%7C%5Cldots%7C%7CTemp_%7B63%7D%7C%7CData%5E0_0%7C%7CData%5E0_1%7C%7CData%5E0_2%7C%7CData%5E0_3">
</p>
5. Use the algorithm describled in section 4, with argument ![LL-inlined] and private key ![k-inlined] describled section 6, to get signature ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r_L%2Cs_L%29).
The bit length of ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_L) and ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_L) shall not be more than 240. Otherwise, repeat this step.
6. Convert ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_L) and ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_L) to hex-integer string ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Br_L%7D) and ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bs_L%7D), without `"0x"` prefix.
If the length of ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Br_L%7D) or ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bs_L%7D) is less than 60, pad character `'0'` until the length is 60.
7. Let ![Data1-inlined] be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Data%5E1%3D%5Ctexttt%7B%2260%22%7D%7C%7CSZ%5E%7Bs_L%7D%7C%7CSZ%5E%7Br_L%7D">
</p>
8. Let ![Temp-inlined] be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Temp%3DU%7C%7CData%5E0">
</p>
Use the algorithm describled in section 4, with argument ![Temp-inlined] and private key ![k-inlined] describled section 6, to get signature ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r_%7BTemp%7D%2Cs_%7BTemp%7D%29).
The bit length of ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_%7BTemp%7D) and ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_%7BTemp%7D) shall not be more than 240. Otherwise, repeat this step.
9. Convert ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_%7BTemp%7D) and ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_%7BTemp%7D) to hex-integer string ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Br_%7BTemp%7D%7D) and ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bs_%7BTemp%7D%7D), without `"0x"` prefix.
If the length of ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Br_%7BTemp%7D%7D) or ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bs_%7BTemp%7D%7D) is less than 60, pad character `'0'` until the length is 60.
10. Let ![Data2-inlined] be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Data%5E2%3D%5Ctexttt%7B%2260%22%7D%7C%7CSZ%5E%7Bs_%7BTemp%7D%7D%7C%7CSZ%5E%7Br_%7BTemp%7D%7D">
</p>
11. Calculate CRC32 value of
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?L%7C%7CU%7C%7CData%5E0%7C%7CData%5E1%7C%7CData%5E2%7C%7CData%5E3">
</p>
The final checksum the complement of CRC32 value.
Then convert the checksum to decimal string ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bchecksum%7D). If the length is less than 10, pad character `'0'` until the length is 10.
12. Let ![Data-inlined] be
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cinline%20Data%3DData%5E0%7C%7CData%5E1%7C%7CData%5E2%7C%7CData%5E3%7C%7CSZ%5E%7Bchecksum%7D">
</p>
13. Output with format
* A fixed header `"RAR registration data"`, taking one line.
* Username, taking one line.
* License type, taking one line
* UID, taking one line, with format:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Ctexttt%7B%22UID%3D%22%7D%7C%7CUID">
</p>
* Output ![Data-inlined], with 54 characters a line.

View file

@ -0,0 +1,320 @@
[GF2-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BGF%7D%282%29
[GF2p15-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BGF%7D%282%5E%7B15%7D%29
[GF2p15p17-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29
[A-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20A
[B-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20B
[D-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20D
[G-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20G
[M-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20M
[P-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20P
[h-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20h
[k-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20k
[l-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20l
[n-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20n
[r-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20r
[s-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20s
[T-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20T
[UU-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20U
[LL-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20L
[Rnd-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Rnd
[Temp-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Temp
[UID-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20UID
[Data-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data
[Data0-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E0
[Data1-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E1
[Data2-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E2
[Data3-inlined]: http://latex.codecogs.com/svg.latex?%5Cinline%20Data%5E3
# "rarreg.key"是如何生成的?
WinRAR使用了基于ECC的签名算法来生成 `rarreg.key` 文件其使用的签名算法是中国SM2数字签名算法的变体。与各种标准ECDSA不同的是WinRAR使用的椭圆曲线是一个基于复合域 ![GF2p15p17-inlined] 上的曲线。
## 1. 复合域 ![GF2p15p17-inlined]
基域 ![GF2p15-inlined] 采用标准基(多项式基)来表达,采用的不可约多项式为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?P%28%5Calpha%29%3D%5Calpha%5E%7B15%7D&plus;%5Calpha&plus;1")
</p>
各项系数全部位于 ![GF2-inlined]。设基域的标准基为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B_1%3D%5C%7B1%2C%5Calpha%2C%5Calpha%5E2%2C%5Cldots%2C%5Calpha%5E%7B14%7D%5C%7D")
</p>
则位于基域 ![GF2p15-inlined] 上的元素 ![A-inlined] 可以用如下方式表达:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?A%3D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_i%5Calpha%5Ei%20%5Cquad%20%5Cquad%20%5Cquad%20a_i%5Cin%5Ctextrm%7BGF%7D%282%29")
</p>
---
复合域 ![GF2p15p17-inlined] 的不可约多项式为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Q%28%5Cbeta%29%3D%5Cbeta%5E%7B17%7D&plus;%5Cbeta%5E3&plus;1")
</p>
各项系数全部位于 ![GF2p15-inlined]。设复合域的标准基为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B_2%3D%5C%7B1%2C%5Cbeta%2C%5Cbeta%5E2%2C%5Cldots%2C%5Cbeta%5E%7B16%7D%5C%7D")
</p>
则位于复合域 ![GF2p15p17-inlined] 上的元素 ![B-inlined] 可以用如下方式表达:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%28%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Calpha%5Ei%29%5Cbeta%5Ej%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Calpha%5Ei%5Cbeta%5Ej%20%5Cquad%20%5Cquad%20%5Cquad%20a_%7Bj%2Ci%7D%5Cin%5Ctextrm%7BGF%7D%282%29")
</p>
---
为了方便表述我们用255比特的大数 ![D-inlined] 来表示位于复合域 ![GF2p15p17-inlined] 上的元素 ![B-inlined]。它们的对应关系为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?B%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Calpha%5Ei%5Cbeta%5Ej%20%5Cleftrightarrow%20D%3D%5Csum_%7Bj%3D0%7D%5E%7B16%7D%5Csum_%7Bi%3D0%7D%5E%7B14%7Da_%7Bj%2Ci%7D%5Ccdot%202%5E%7B15j&plus;i%7D")
</p>
## 2. 复合域 ![GF2p15p17-inlined] 上的椭圆曲线
曲线方程为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?y%5E2&plus;xy%3Dx%5E3&plus;161%20%5Cquad%20%5Cquad%20%5Cquad%20161%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29")
</p>
基点 ![G-inlined] 为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20G%26%3D%28G_x%2CG_y%29%20%5C%5C%20G_x%26%3D%5Ctextrm%7B0x56fdcbc6a27acee0cc2996e0096ae74feb1acf220a2341b898b549440297b8cc%7D%20%5Cquad%20G_x%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%5C%5C%20G_y%26%3D%5Ctextrm%7B0x20da32e8afc90b7cf0e76bde44496b4d0794054e6ea60f388682463132f931a7%7D%20%5Cquad%20G_y%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%20%5Cend%7Baligned%7D")
</p>
基点 ![G-inlined] 的阶 ![n-inlined] 为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?n%3D%5Ctextrm%7B0x1026dd85081b82314691ced9bbec30547840e4bf72d8b5e0d258442bbcd31%7D%20%5Cquad%20n%5Cin%5Cnolinebreak%5Cmathbb%7BZ%7D")
</p>
## 3. 消息哈希算法
设长度为 ![l-inlined] 的消息为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?M%3Dm_0m_1%20%5Cldots%20m_%7Bl-1%7D%20%5Cquad%20%5Cquad%20m_i%5Cin%5B0%2C%20256%29")
</p>
则消息 ![M-inlined] 的SHA1值为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Ctextrm%7BSHA%7D_1%28M%29%3DS_0%7C%7CS_1%7C%7CS_2%7C%7CS_3%7C%7CS_4%20%5Cquad%20%5Cquad%20S_i%5Cin%5B0%2C%202%5E%7B32%7D%29")
</p>
其中 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20S_0%2CS_1%2CS_2%2CS_3%2CS_4) 为SHA1算法输出时的5个状态值将这5个状态值按照大端字节序依次输出即为的SHA1哈希值 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%5Ctextrm%7BSHA%7D_1%28M%29)。
WinRAR在做完SHA1计算后采用大数 ![h-inlined] 作为ECC签名时消息的哈希
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?h%3D%28%5Csum_%7Bi%3D0%7D%5E%7B4%7DS_i%20%5Ccdot%202%5E%7B32i%7D%29&plus;%5Ctextrm%7B0x1bd10xb4e33c7c0ffd8d43%7D%20%5Ccdot%202%5E%7B32*5%7D")
</p>
## 4. ECC签名算法
设私钥为 ![k-inlined],公钥为 ![P-inlined],即:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?P%3Dk%20%5Ccdot%20G")
</p>
消息哈希为 ![h-inlined],则签名 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r%2Cs%29) 为:
1. 生成随机数 ![Rnd-inlined],满足 ![](http://latex.codecogs.com/svg.latex?%5Cinline%200%3CRnd%3Cn)。
2. 计算 ![r-inlined]
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?r%3D%28%28Rnd%20%5Ccdot%20G%29_x&plus;h%29%5C%20%5C%20Mod%5C%20%5C%20n">
</p>
其中 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28Rnd%20%5Ccdot%20G%29_x) 表示取 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20Rnd%20%5Ccdot%20G) 的X坐标同时将X坐标从 ![GF2p15p17-inlined] 转换为大数。
若 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r%3D0) 或者 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r&plus;Rnd%3Dn) 则回到步骤1。
3. 计算 ![s-inlined]
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?s%3D%28Rnd-kr%29%5C%20%5C%20Mod%5C%20%5C%20n">
</p>
若 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s%3D0) 则回到步骤1。
4. 输出 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r%2Cs%29)。
## 5. WinRAR的私钥生成算法
该算法会利用长度为 ![l-inlined] 的数据
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?T%3Dt_0t_1%20%5Cldots%20t_%7Bl-1%7D%20%5Cquad%20%5Cquad%20t_i%5Cin%5B0%2C256%29">
</p>
来生成私钥 ![k-inlined]。
1. 设6个32位整数为 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_0%2Cg_1%2Cg_2%2Cg_3%2Cg_4%2Cg_5),则有
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?g_j%3D%5Csum_%7Bi%3D0%7D%5E%7B3%7Dg_%7Bj%2Ci%7D%20%5Ccdot%202%5E%7B8i%7D%20%5Cquad%20%5Cquad%20g_%7Bj%2Ci%7D%5Cin%5B0%2C256%29">
</p>
2. 令 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_0%3D0)。
3. 如果 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20l%5Cneq%200) 则计算 ![T-inlined] 的SHA1值并将状态值 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20S_i) 赋值给 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_%7Bi&plus;1%7D)
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20%5Ctextrm%7BSHA%7D_1%28T%29%26%3DS_0%7C%7CS_1%7C%7CS_2%7C%7CS_3%7C%7CS_4%20%5C%5C%20g_1%26%3DS_0%20%5C%5C%20g_2%26%3DS_1%20%5C%5C%20g_3%26%3DS_2%20%5C%5C%20g_4%26%3DS_3%20%5C%5C%20g_5%26%3DS_4%20%5C%5C%20%5Cend%7Baligned%7D">
</p>
否则,即 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20l%3D0) 时,令:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20g_1%26%3D%5Ctextrm%7B0xeb3eb781%7D%20%5C%5C%20g_2%26%3D%5Ctextrm%7B0x50265329%7D%20%5C%5C%20g_3%26%3D%5Ctextrm%7B0xdc5ef4a3%7D%20%5C%5C%20g_4%26%3D%5Ctextrm%7B0x6847b9d5%7D%20%5C%5C%20g_5%26%3D%5Ctextrm%7B0xcde43b4c%7D%20%5C%5C%20%5Cend%7Baligned%7D">
</p>
4. 把 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20g_0) 作为计数器自增1。
计算SHA1值
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Ctextrm%7BSHA%7D_1%28g_%7B0%2C0%7D%7C%7Cg_%7B0%2C1%7D%7C%7Cg_%7B0%2C2%7D%7C%7Cg_%7B0%2C3%7D%7C%7Cg_%7B1%2C0%7D%7C%7Cg_%7B1%2C1%7D%7C%7C%5Cldots%7C%7Cg_%7B5%2C0%7D%7C%7Cg_%7B5%2C1%7D%7C%7Cg_%7B5%2C2%7D%7C%7Cg_%7B5%2C3%7D%29%3DS_0%7C%7CS_1%7C%7CS_2%7C%7CS_3%7C%7CS_4">
</p>
取 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20S_0) 的低16位并记为 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_%7Bg_0%7D)。
5. 步骤4再重复14次。
6. 重复执行完后会得到 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_1%2Ck_2%2Ck_3%2C%5Cldots%2Ck_%7B15%7D),则输出私钥
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?k%3D%5Csum_%7Bi%3D1%7D%5E%7B15%7Dk_i%20%5Ccdot%202%5E%7B16i%7D">
</p>
## 6. WinRAR的公钥和私钥
WinRAR的私钥 ![k-inlined] 为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?k%3D%5Ctextrm%7B0x59fe6abcca90bdb95f0105271fa85fb9f11f467450c1ae9044b7fd61d65e%7D%20%5Cquad%20%5Cquad%20k%5Cin%5Cnolinebreak%5Cmathbb%7BZ%7D">
</p>
该私钥是通过算法5生成的其中数据 ![T-inlined] 的长度为0。
公钥 ![P-inlined] 为:
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cbegin%7Baligned%7D%20P%26%3D%28P_x%2CP_y%29%20%5C%5C%20P_x%26%3D%5Ctextrm%7B0x3861220ed9b36c9753df09a159dfb148135d495db3af8373425ee9a28884ba1a%7D%20%5Cquad%20P_x%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%20%5C%5C%20P_y%26%3D%5Ctextrm%7B0x12b64e62db43a56114554b0cbd573379338cea9124c8443c4f50e6c8b013ec20%7D%20%5Cquad%20P_y%5Cin%5Ctextrm%7BGF%7D%28%282%5E%7B15%7D%29%5E%7B17%7D%29%20%5Cend%7Baligned%7D">
</p>
## 7. 授权文件"rarreg.key"的生成
授权文件的生成需要两个参数:
1. 用户名的ANSI字符串不包括null-terminator记为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?U%3Du_0u_1%20%5Cldots%20u_%7Bl-1%7D">
</p>
2. 授权类型的ANSI字符串不包括null-terminator记为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?L%3Dl_0l_1%20%5Cldots%20l_%7Bl-1%7D">
</p>
`rarreg.key` 的生成算法如下:
1. 使用用户名 ![UU-inlined] 通过算法5计算出私钥 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_U) 以及公钥 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20P_U),并将公钥 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20P_U) 按照SM2压缩公钥格式以Hex字符串ASCII编码的形式输出。得到的Hex字符串记为临时值 ![Temp-inlined]。
![Temp-inlined] 的长度应该为64若长度不足则在前面补字符`'0'`直到长度为64。
2. 令字符串 ![Data3-inlined]为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Data%5E3%3D%5Ctexttt%7B%2260%22%7D%7C%7CTemp_0%7C%7CTemp_1%7C%7C%5Cldots%7C%7CTemp_%7B47%7D">
</p>
3. 使用 ![Data3-inlined] 通过算法5计算出私钥 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20k_%7BData%5E3%7D) 以及公钥 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20P_%7BData%5E3%7D),并将公钥 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20P_%7BData%5E3%7D) 按照SM2压缩公钥格式以Hex字符串ASCII编码的形式输出。得到的Hex字符串记为 ![Data0-inlined]。
![Data0-inlined] 的长度应该为64若长度不足则在前面补字符`'0'`直到长度为64。
4. 令字符串 ![UID-inlined]为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?UID%3DTemp_%7B48%7D%7C%7CTemp_%7B49%7D%7C%7C%5Cldots%7C%7CTemp_%7B63%7D%7C%7CData%5E0_0%7C%7CData%5E0_1%7C%7CData%5E0_2%7C%7CData%5E0_3">
</p>
5. 对授权类型 ![LL-inlined] 使用算法4得到签名 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r_L%2Cs_L%29)其中私钥见第6节。
要求 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_L) 和 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_L) 的长度都不得超过240比特否则重复该步骤。
6. 将 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_L) 和 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_L) 以16进制形式输出无`"0x"`前缀),分别记为 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Br_L%7D) 和 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bs_L%7D)。
若长度不满60则在前面补字符`'0'`直到长度为60。
7. 令字符串 ![Data1-inlined]为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Data%5E1%3D%5Ctexttt%7B%2260%22%7D%7C%7CSZ%5E%7Bs_L%7D%7C%7CSZ%5E%7Br_L%7D">
</p>
8. 令字符串 ![Temp-inlined]为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Temp%3DU%7C%7CData%5E0">
</p>
对 ![Temp-inlined] 使用算法4得到签名 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20%28r_%7BTemp%7D%2Cs_%7BTemp%7D%29)其中私钥见第6节。
要求 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_%7BTemp%7D) 和 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_%7BTemp%7D) 的长度都不得超过240比特否则重复该步骤。
9. 将 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20r_%7BTemp%7D) 和 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20s_%7BTemp%7D) 以16进制形式输出无`"0x"`前缀),分别记为 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Br_%7BTemp%7D%7D) 和 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bs_%7BTemp%7D%7D)。
若长度不满60则在前面补字符`'0'`直到长度为60。
10. 令字符串 ![Data2-inlined]为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?Data%5E2%3D%5Ctexttt%7B%2260%22%7D%7C%7CSZ%5E%7Bs_%7BTemp%7D%7D%7C%7CSZ%5E%7Br_%7BTemp%7D%7D">
</p>
11. 对
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?L%7C%7CU%7C%7CData%5E0%7C%7CData%5E1%7C%7CData%5E2%7C%7CData%5E3">
</p>
计算CRC32值最终校验和为CRC32值的反。将校验和以10进制形式输出若长度不满10则在前面补字符`'0'`直到长度为10记为 ![](http://latex.codecogs.com/svg.latex?%5Cinline%20SZ%5E%7Bchecksum%7D)。
12. 令字符串 ![Data-inlined]为
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Cinline%20Data%3DData%5E0%7C%7CData%5E1%7C%7CData%5E2%7C%7CData%5E3%7C%7CSZ%5E%7Bchecksum%7D">
</p>
13. 格式化输出。
* 固定文件头`"RAR registration data"`,占一行。
* 用户名,占一行。
* 授权类型,占一行。
* UID占一行
<p align="center">
<img src="http://latex.codecogs.com/svg.latex?%5Ctexttt%7B%22UID%3D%22%7D%7C%7CUID">
</p>
* 将 ![Data-inlined] 按照每行54个字符输出。

87
README.md Normal file
View file

@ -0,0 +1,87 @@
# WinRAR-Keygen
[中文版 README](README.zh-CN.md)
<img src="icon1.png" alt="icon1" style="zoom:50%;" />
## 1. What is WinRAR?
WinRAR is a trialware file archiver utility for Windows, developed by Eugene Roshal of win.rar GmbH.
It can create and view archives in RAR or ZIP file formats and unpack numerous archive file formats.
WinRAR is not a free software. If you want to use it, you should pay to [__RARLAB__](https://rarlab.com/) and then you will get a license file named `rarreg.key`.
This repository will tell you how WinRAR license file `"rarreg.key"` is generated.
## 2. How is "rarreg.key" generated?
See [here](README.HOW_DOES_IT_WORK.md).
## 3. How to build?
### 3.1 Prerequisites
1. Please make sure that you have __Visual Studio 2019__ or the higher. Because this is a VS2019 project.
2. Please make sure you have installed `vcpkg` and the following libraries:
* `mpir:x86-windows-static`
* `mpir:x64-windows-static`
is installed.
You can install them by:
```console
$ vcpkg install mpir:x86-windows-static
$ vcpkg install mpir:x64-windows-static
```
3. Your `vcpkg` has been integrated into your __Visual Studio__, which means you have run
```console
$ vcpkg integrate install
```
successfully.
### 3.2 Build
1. Open this project in __Visual Studio__.
2. Select `Release` configuration.
3. Select __Build > Build Solution__.
You will see executable files in `bin/` directory.
## 4. How to Use?
```
Usage:
winrar-keygen.exe <your name> <license type>
Example:
winrar-keygen.exe "Rebecca Morrison" "Single PC usage license"
or:
winrar-keygen.exe "Rebecca Morrison" "Single PC usage license" > rarreg.key
```
Now you can see the newly generated file. Save the generated information as `rarreg.key`.
```console
$ winrar-keygen.exe "DoubleLabyrinth" "Single PC usage license"
RAR registration data
DoubleLabyrinth
Single PC usage license
UID=d2fb7cb15c078a3def58
6412212250ef58bef21cdcb49ca34b7040112cae5a512f1adad1a8
f6d2ee8c382fe64f8e3d6035c6ab9048e2c5c62f0238f183d28519
aa87488bf38f5b634cf28190bdf438ac593b1857cdb55a7fcb0eb0
c3e4c2736090b3dfa45384e08e9de05c5860d3051942adf2db9d96
e2ec37f1cfae00b3e2455093b90e4e352f016f6b9853c735d45fb4
01f9cbb91d3f3ac5664511229f8c9b0a9e1d61a2e087b481607e91
bfc8a83414f6807d31a5f8c587513aa54f9b1249ad804214409316
```

81
README.zh-CN.md Normal file
View file

@ -0,0 +1,81 @@
# WinRAR-Keygen
[README for English](README.md)
<img src="icon1.png" alt="icon1" style="zoom:50%;" />
## 1. WinRAR是什么
WinRAR是一款用于管理压缩包文件的共享软件。其算法由作者尤金·罗谢尔研发享有原创专利。
它可以用来创建或浏览RAR、ZIP等众多格式的压缩包。
WinRAR不是免费的软件。如果你想使用它你应当向 [__RARLAB__](https://rarlab.com/) 付费,然后获得一个授权文件 `rarreg.key`
这份repo将会告诉你 `rarreg.key` 是如何生成的。
## 2. "rarreg.key"是如何生成的?
见 [这里](README.HOW_DOES_IT_WORK.zh-CN.md)。
## 3. 如何编译?
### 3.1 前提条件
1. 请确保你有 __Visual Studio 2019__ 或其更高版本。因为这是一个VS2019项目。
2. 请确保你安装了 `vcpkg` 以及下面几个库:
* `mpir:x86-windows-static`
* `mpir:x64-windows-static`
你可以通过下的命令来安装:
```console
$ vcpkg install mpir:x86-windows-static
$ vcpkg install mpir:x64-windows-static
```
3. 你的 `vcpkg`__Visual Studio__ 整合了,即你曾成功运行了下面这条命令:
```console
$ vcpkg integrate install
```
### 3.2 编译
1. 在 __Visual Studio__ 中打开这个项目。
2. 选择 `Release` 配置。
3. 选择 __生成 > 生成解决方案__
## 4. 如何使用?
```
Usage:
winrar-keygen.exe <your name> <license type>
Example:
winrar-keygen.exe "Rebecca Morrison" "Single PC usage license"
or:
winrar-keygen.exe "Rebecca Morrison" "Single PC usage license" > rarreg.key
```
现在你可以看到新生成的文件,将生成的信息保存为 `rarreg.key ` 即可:
```console
$ winrar-keygen.exe "DoubleLabyrinth" "Single PC usage license"
RAR registration data
DoubleLabyrinth
Single PC usage license
UID=d2fb7cb15c078a3def58
6412212250ef58bef21cdcb49ca34b7040112cae5a512f1adad1a8
f6d2ee8c382fe64f8e3d6035c6ab9048e2c5c62f0238f183d28519
aa87488bf38f5b634cf28190bdf438ac593b1857cdb55a7fcb0eb0
c3e4c2736090b3dfa45384e08e9de05c5860d3051942adf2db9d96
e2ec37f1cfae00b3e2455093b90e4e352f016f6b9853c735d45fb4
01f9cbb91d3f3ac5664511229f8c9b0a9e1d61a2e087b481607e91
bfc8a83414f6807d31a5f8c587513aa54f9b1249ad804214409316
```

486
WinRarConfig.hpp Normal file
View file

@ -0,0 +1,486 @@
#pragma once
#include "GaloisField.hpp"
#include "EllipticCurveGF2m.hpp"
#include "BigInteger.hpp"
struct WinRarConfig {
public:
// Irreducible polynomial of ground field = x^15 + x + 1
// Irreducible polynomial of extension field = y^17 + y^3 + 1;
struct GF2p15p17Traits {
struct ElementType {
uint16_t Items[17];
};
static constexpr size_t BitSizeValue = 15 * 17;
static constexpr size_t DumpSizeValue = (BitSizeValue + 7) / 8;
using GF2p15LogExpTableType = uint16_t[0x8000];
static const GF2p15LogExpTableType& InitializeGF2p15Table(bool ReturnLogTable) noexcept {
static GF2p15LogExpTableType LogTable;
static GF2p15LogExpTableType ExpTable;
constexpr size_t Order = 0x7fff;
if (ExpTable[Order] == 0) {
ExpTable[0] = 1;
for (size_t i = 1; i < Order; ++i) {
uint32_t temp = ExpTable[i - 1] * 2;
if (temp & 0x8000) {
temp ^= 0x8003;
}
ExpTable[i] = temp;
}
// mark as initialized
ExpTable[Order] = ~ExpTable[Order];
for (size_t i = 0; i < Order; ++i) {
// #if defined(_MSC_VER)
// __assume(ExpTable[i] <= Order);
// #endif
LogTable[ExpTable[i]] = static_cast<uint16_t>(i);
}
}
if (ReturnLogTable) {
return LogTable;
} else {
return ExpTable;
}
}
static inline const GF2p15LogExpTableType& GF2p15LogTable = InitializeGF2p15Table(true);
static inline const GF2p15LogExpTableType& GF2p15ExpTable = InitializeGF2p15Table(false);
static inline const ElementType ZeroValue = {};
static inline const ElementType OneValue = { 1 };
static void Verify(const ElementType& Val) {
for (size_t i = 0; i < 17; ++i) {
if (Val.Items[i] >= 0x8000) {
throw std::invalid_argument("Val is not in GF((2 ^ 15) ^ 17).");
}
}
}
static size_t Dump(const ElementType& Val, void* lpBuffer, size_t cbBuffer) {
if (cbBuffer < DumpSizeValue) {
throw std::length_error("Insufficient buffer.");
} else {
uint8_t* pbWritePtr = reinterpret_cast<uint8_t*>(lpBuffer);
unsigned left_bits = 8;
for (size_t i = 0; i < 17; ++i) {
uint8_t low8 = static_cast<uint8_t>(Val.Items[i]);
uint8_t high7 = static_cast<uint8_t>(Val.Items[i] >> 8);
if (left_bits == 8) {
*pbWritePtr = low8;
++pbWritePtr;
} else {
*pbWritePtr |= low8 << (8 - left_bits);
++pbWritePtr;
*pbWritePtr = low8 >> left_bits;
}
if (left_bits == 8) {
*pbWritePtr = high7;
left_bits = 1;
} else if (left_bits == 7) {
*pbWritePtr |= high7 << 1;
++pbWritePtr;
left_bits = 8;
} else {
*pbWritePtr |= high7 << (8 - left_bits);
++pbWritePtr;
*pbWritePtr = high7 >> left_bits;
left_bits = 8 - (7 - left_bits);
}
}
return DumpSizeValue;
}
}
static std::vector<uint8_t> Dump(const ElementType& Val) noexcept {
std::vector<uint8_t> bytes(DumpSizeValue);
Dump(Val, bytes.data(), bytes.size());
return bytes;
}
static void Load(ElementType& Val, const void* lpBuffer, size_t cbBuffer) {
if (cbBuffer != DumpSizeValue) {
throw std::length_error("The length of buffer is not correct.");
} else {
const uint8_t* pbBuffer = reinterpret_cast<const uint8_t*>(lpBuffer);
if (pbBuffer[DumpSizeValue - 1] & 0x80) {
throw std::invalid_argument("Not in GF((2 ^ 15) ^ 17).");
}
uint16_t* pbWritePtr = Val.Items;
unsigned left_bits = 15;
for (size_t i = 0; i < DumpSizeValue; ++i) {
uint16_t v;
if (left_bits == 15) {
v = pbBuffer[i];
left_bits = 15 - 8;
} else if (left_bits > 8) {
v |= pbBuffer[i] << (15 - left_bits);
left_bits -= 8;
} else {
v |= (pbBuffer[i] << (15 - left_bits)) & 0x7fff;
*pbWritePtr = v;
++pbWritePtr;
v = pbBuffer[i] >> left_bits;
left_bits = 15 - (8 - left_bits);
}
}
}
}
static void Load(ElementType& Val, const std::vector<uint8_t>& Buffer) {
Load(Val, Buffer.data(), Buffer.size());
}
static inline void Swap(ElementType& A, ElementType& B) noexcept {
for (size_t i = 0; i < 17; ++i) {
std::swap(A.Items[i], B.Items[i]);
}
}
static inline void SetZero(ElementType& Val) noexcept {
memset(Val.Items, 0, sizeof(Val.Items));
}
static inline void SetOne(ElementType& Val) noexcept {
Val.Items[0] = 1;
memset(Val.Items + 1, 0, sizeof(Val.Items) - sizeof(Val.Items[0]));
}
static inline bool IsEqual(const ElementType& A, const ElementType& B) noexcept {
return memcmp(A.Items, B.Items, sizeof(ElementType::Items)) == 0;
}
static inline bool IsZero(const ElementType& Val) noexcept {
return memcmp(Val.Items, ZeroValue.Items, sizeof(ElementType::Items)) == 0;
}
static inline bool IsOne(const ElementType& Val) noexcept {
return memcmp(Val.Items, OneValue.Items, sizeof(ElementType::Items)) == 0;
}
// Result = A + B
static inline void Add(ElementType& Result, const ElementType& A, const ElementType& B) noexcept {
for (size_t i = 0; i < 17; ++i) {
Result.Items[i] = A.Items[i] ^ B.Items[i];
}
}
// A += B
static inline void AddAssign(ElementType& A, const ElementType& B) noexcept {
for (size_t i = 0; i < 17; ++i) {
A.Items[i] ^= B.Items[i];
}
}
// Result = A + 1
static inline void AddOne(ElementType& Result, const ElementType& A) noexcept {
Result.Items[0] = A.Items[0] ^ 0x0001;
memcpy(Result.Items + 1, A.Items + 1, sizeof(ElementType::Items) - sizeof(uint16_t));
}
// A += 1
static inline void AddOneAssign(ElementType& A) noexcept {
A.Items[0] ^= 0x0001;
}
// Result = A - B
static inline void Substract(ElementType& Result, const ElementType& A, const ElementType& B) noexcept {
for (size_t i = 0; i < 17; ++i) {
Result.Items[i] = A.Items[i] ^ B.Items[i];
}
}
// A -= B
static inline void SubstractAssign(ElementType& A, const ElementType& B) noexcept {
for (size_t i = 0; i < 17; ++i) {
A.Items[i] ^= B.Items[i];
}
}
// Result = A - 1
static inline void SubstractOne(ElementType& Result, const ElementType& A) noexcept {
Result.Items[0] = A.Items[0] ^ 0x0001;
memcpy(Result.Items + 1, A.Items + 1, sizeof(ElementType::Items) - sizeof(uint16_t));
}
// A -= 1
static inline void SubstractOneAssign(ElementType& A) noexcept {
A.Items[0] ^= 0x0001;
}
// Result = A * B
// Require: len(Result) == M + N - 1
static inline void FullMultiplySchoolBook(size_t M, size_t N, uint16_t Result[], const uint16_t A[], const uint16_t B[]) noexcept {
memset(Result, 0, (M + N - 1) * sizeof(uint16_t));
for (size_t i = 0; i < M; ++i) {
if (A[i]) {
for (size_t j = 0; j < N; ++j) {
if (B[j]) {
auto g = GF2p15LogTable[A[i]] + GF2p15LogTable[B[j]];
if (g >= 0x7fff) {
g -= 0x7fff;
}
Result[i + j] ^= GF2p15ExpTable[g];
}
}
}
}
}
static inline void ModularReduction(size_t N, uint16_t A[]) noexcept {
// Irreducible polynomial of extension field = y^17 + y^3 + 1;
for (size_t i = N - 1; i > 16; --i) {
if (A[i] != 0) {
A[i - 17 + 0] ^= A[i];
A[i - 17 + 3] ^= A[i];
A[i] = 0;
}
}
}
// Result = A * B mod (x^15 + x + 1, y^17 + y^3 + 1)
static inline void Multiply(ElementType& Result, const ElementType& A, const ElementType& B) noexcept {
uint16_t temp[16 + 16 + 1];
FullMultiplySchoolBook(17, 17, temp, A.Items, B.Items);
ModularReduction(16 + 16 + 1, temp);
memcpy(Result.Items, temp, sizeof(ElementType::Items));
}
static inline void MultiplyAssign(ElementType& A, const ElementType& B) noexcept {
Multiply(A, A, B);
}
static inline void Divide(ElementType& Result, const ElementType& A, const ElementType& B) {
ElementType InverseOfB;
Inverse(InverseOfB, B);
Multiply(Result, A, InverseOfB);
}
static inline void DivideAssign(ElementType& A, const ElementType& B) {
ElementType InverseOfB;
Inverse(InverseOfB, B);
MultiplyAssign(A, InverseOfB);
}
static inline void Inverse(ElementType& Result, const ElementType& A) {
// lpA += (Alpha * x ^ j) * B
auto AddScale = [](uint16_t A[], size_t& degA, uint16_t Alpha, size_t j, const uint16_t B[], size_t degB) {
auto logAlpha = GF2p15LogTable[Alpha];
auto Aj = A + j;
for (size_t i = 0; i <= degB; ++i) {
if (B[i]) {
auto g = logAlpha + GF2p15LogTable[B[i]];
if (g >= 0x7fff) {
g -= 0x7fff;
}
Aj[i] ^= GF2p15ExpTable[g];
if (Aj[i] && i + j > degA) {
degA = i + j;
}
}
}
while (A[degA] == 0) {
--degA;
}
};
size_t degB;
size_t degC;
size_t degF;
size_t degG;
uint16_t B[2 * 17];
uint16_t C[2 * 17];
uint16_t F[2 * 17];
uint16_t G[2 * 17];
// Initialize B
degB = 0;
B[0] = 1;
memset(B + 1, 0, sizeof(B) - sizeof(uint16_t));
// Initialize C
degC = 0;
memset(C, 0, sizeof(C));
// Initialize F
bool isZero = true;
for (unsigned i = 0; i < 17; ++i) {
if (A.Items[i] != 0) {
isZero = false;
}
F[i] = A.Items[i];
if (F[i]) {
degF = i;
}
}
memset(F + 17, 0, 17 * sizeof(uint16_t));
if (isZero) {
throw std::domain_error("Zero doesn't have inverse.");
}
// initialize G = x^17 + x^3 + 1;
degG = 17;
memset(G, 0, sizeof(G));
G[0] = 1;
G[3] = 1;
G[17] = 1;
for (uint16_t *lpF = F, *lpG = G, *lpB = B, *lpC = C;;) {
if (degF == 0) {
for (size_t i = 0; i <= degB; ++i) {
if (lpB[i]) {
auto g = GF2p15LogTable[lpB[i]] - GF2p15LogTable[lpF[0]];
if (g < 0) {
g += 0x7fff;
}
Result.Items[i] = GF2p15ExpTable[g];
} else {
Result.Items[i] = 0;
}
}
for (size_t i = degB + 1; i < 17; ++i) {
Result.Items[i] = 0;
}
break;
}
if (degF < degG) {
std::swap(lpF, lpG);
std::swap(degF, degG);
std::swap(lpB, lpC);
std::swap(degB, degC);
}
auto j = degF - degG;
auto g = GF2p15LogTable[lpF[degF]] - GF2p15LogTable[lpG[degG]];
if (g < 0) {
g += 0x7fff;
}
auto Alpha = GF2p15ExpTable[g];
AddScale(lpF, degF, Alpha, j, lpG, degG);
AddScale(lpB, degB, Alpha, j, lpC, degC);
}
}
static inline void InverseAssign(ElementType& Result) {
Inverse(Result, Result);
}
static inline void Square(ElementType& Result, const ElementType& A) noexcept {
uint16_t temp[16 + 16 + 1];
for (size_t i = 0; i < 17; ++i) {
if (A.Items[i]) {
auto g = GF2p15LogTable[A.Items[i]] * 2;
if (g >= 0x7fff) {
g -= 0x7fff;
}
temp[2 * i] = GF2p15ExpTable[g];
} else {
temp[2 * i] = 0;
}
}
for (size_t i = 1; i < 16 + 16 + 1; i += 2) {
temp[i] = 0;
}
ModularReduction(16 + 16 + 1, temp);
memcpy(Result.Items, temp, sizeof(ElementType::Items));
}
static inline void SquareAssign(ElementType& A) noexcept {
Square(A, A);
}
};
static inline const EllipticCurveGF2m<GaloisField<GF2p15p17Traits>> Curve{
{ GaloisFieldInitByZero{} }, // A
{ GaloisFieldInitByElement{}, { 161 } } // B
};
static inline const EllipticCurveGF2m<GaloisField<GF2p15p17Traits>>::Point G = Curve.GetPoint(
{
GaloisFieldInitByElement{},
{
0x38CC, 0x052F, 0x2510, 0x45AA,
0x1B89, 0x4468, 0x4882, 0x0D67,
0x4FEB, 0x55CE, 0x0025, 0x4CB7,
0x0CC2, 0x59DC, 0x289E, 0x65E3,
0x56FD
}
},
{
GaloisFieldInitByElement{},
{
0x31A7, 0x65F2, 0x18C4, 0x3412,
0x7388, 0x54C1, 0x539B, 0x4A02,
0x4D07, 0x12D6, 0x7911, 0x3B5E,
0x4F0E, 0x216F, 0x2BF2, 0x1974,
0x20DA
}
}
);
static inline const BigInteger Order = "0x1026dd85081b82314691ced9bbec30547840e4bf72d8b5e0d258442bbcd31";
// Generated by `WinRarKeygen<WinRarConfig>::GeneratePrivateKey(nullptr, 0);`
static inline const BigInteger PrivateKey = "0x59fe6abcca90bdb95f0105271fa85fb9f11f467450c1ae9044b7fd61d65e";
static inline const EllipticCurveGF2m<GaloisField<GF2p15p17Traits>>::Point PublicKey = Curve.GetPoint(
{
GaloisFieldInitByElement{},
{
0x3A1A, 0x1109, 0x268A, 0x12F7,
0x3734, 0x75F0, 0x576C, 0x2EA4,
0x4813, 0x3F62, 0x0567, 0x784D,
0x753D, 0x6D92, 0x366C, 0x1107,
0x3861
}
},
{
GaloisFieldInitByElement{},
{
0x6C20, 0x6027, 0x1B22, 0x7A87,
0x43C4, 0x1908, 0x2449, 0x4675,
0x7933, 0x2E66, 0x32F5, 0x2A58,
0x1145, 0x74AC, 0x36D0, 0x2731,
0x12B6
}
}
);
};

233
WinRarKeygen.hpp Normal file
View file

@ -0,0 +1,233 @@
#pragma once
#include "BigInteger.hpp"
#include "Hasher.hpp"
#include "HasherSha1Traits.hpp"
#include "HasherCrc32Traits.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string>
#include <utility>
template<typename __ConfigType>
class WinRarKeygen {
public:
struct RegisterInfo {
std::string UserName;
std::string LicenseType;
std::string UID;
std::string Items[4];
uint32_t Checksum;
std::string HexData;
};
private:
struct ECCSignature {
BigInteger r;
BigInteger s;
};
static BigInteger GeneratePrivateKey(const void* lpSeed, size_t cbSeed) {
uint32_t Generator[6];
uint16_t RawPrivateKey[15] = {};
if (cbSeed) {
Hasher Sha1(HasherSha1Traits{}, lpSeed, cbSeed);
HasherSha1Traits::DigestType Sha1Digest;
Sha1Digest = Sha1.Evaluate();
for (unsigned i = 0; i < 5; ++i) {
Generator[i + 1] = _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]);
}
} else {
Generator[1] = 0xeb3eb781;
Generator[2] = 0x50265329;
Generator[3] = 0xdc5ef4a3;
Generator[4] = 0x6847b9d5;
Generator[5] = 0xcde43b4c;
}
for (uint32_t i = 0; i < 15; ++i) {
Hasher Sha1(HasherSha1Traits{});
HasherSha1Traits::DigestType Sha1Digest;
Generator[0] = i + 1;
Sha1.Update(Generator, sizeof(Generator));
Sha1Digest = Sha1.Evaluate();
RawPrivateKey[i] = static_cast<uint16_t>(
_byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[0])
);
}
// `Order` has 241 bits, while `RawPrivateKey` has (15 * 16 = 240) bits at most
// So `RawPrivateKey` must be less than `Order` which means `RawPrivateKey` must be valid private key.
return BigInteger(false, RawPrivateKey, sizeof(RawPrivateKey), true);
}
static auto GeneratePublicKey(const BigInteger& PrivateKey) {
return __ConfigType::G * PrivateKey;
}
static std::string GeneratePublicKeySM2CompressedFormat(const char* lpszMessage) {
auto PrivateKey = GeneratePrivateKey(lpszMessage, strlen(lpszMessage));
auto PublicKey = GeneratePublicKey(PrivateKey);
auto PublicKeyCompressed = PublicKey.DumpCompressed();
auto PublicKeyXInteger = BigInteger(false, PublicKeyCompressed.data() + 1, PublicKeyCompressed.size() - 1, false); // 255 bits at most
PublicKeyXInteger *= 2; // 256 bits at most
if (PublicKeyCompressed[0] == 0x03) { // when LSB(PublicKeyY / PublicKeyX) == 1
PublicKeyXInteger.SetBit(0);
}
auto PublicKeyCompressedSM2Format = PublicKeyXInteger.ToString(16, true);
if (PublicKeyCompressedSM2Format.length() < 32 * 2) {
PublicKeyCompressedSM2Format.insert(PublicKeyCompressedSM2Format.begin(), 32 * 2 - PublicKeyCompressedSM2Format.size(), '0');
}
return PublicKeyCompressedSM2Format;
}
static BigInteger GenerateRandomInteger() {
uint16_t RawRandomInteger[15];
srand(static_cast<unsigned int>(time(nullptr)));
for (size_t i = 0; i < 15; ++i) {
RawRandomInteger[i] = static_cast<uint16_t>(rand());
}
return BigInteger(false, RawRandomInteger, sizeof(RawRandomInteger), true);
}
static BigInteger GenerateHashInteger(const void* lpMessage, size_t cbMessage) {
uint32_t RawHash[10];
Hasher Sha1(HasherSha1Traits{}, lpMessage, cbMessage);
HasherSha1Traits::DigestType Sha1Digest = Sha1.Evaluate();
for (size_t i = 0; i < 5; ++i) {
RawHash[i] = _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]);
}
// SHA1("") with all-zeroed initial value
RawHash[5] = 0x0ffd8d43;
RawHash[6] = 0xb4e33c7c;
RawHash[7] = 0x53461bd1;
RawHash[8] = 0x0f27a546;
RawHash[9] = 0x1050d90d;
return BigInteger(false, RawHash, 15 * sizeof(uint16_t), true); // take first 240 bits
}
static ECCSignature Sign(const void* lpData, size_t cbData) {
ECCSignature Signature;
BigInteger Hash = GenerateHashInteger(lpData, cbData);
while (true) {
BigInteger Random = GenerateRandomInteger();
//
// Calculate Signature.r
//
Signature.r.Load(false, (__ConfigType::G * Random).GetX().Dump(), true);
Signature.r += Hash;
Signature.r %= __ConfigType::Order;
if (Signature.r.IsZero() || Signature.r + Random == __ConfigType::Order) {
continue;
}
//
// Calculate Signature.s
//
Signature.s = Random - __ConfigType::PrivateKey * Signature.r;
Signature.s %= __ConfigType::Order;
if (Signature.s.IsZero()) {
continue;
}
break;
}
return Signature;
}
static void CalculateChecksum(RegisterInfo& Info) {
Hasher Crc32(HasherCrc32Traits<0xEDB88320>{});
Crc32.Update(Info.LicenseType.c_str(), Info.LicenseType.length());
Crc32.Update(Info.UserName.c_str(), Info.UserName.length());
Crc32.Update(Info.Items[0].c_str(), Info.Items[0].length());
Crc32.Update(Info.Items[1].c_str(), Info.Items[1].length());
Crc32.Update(Info.Items[2].c_str(), Info.Items[2].length());
Crc32.Update(Info.Items[3].c_str(), Info.Items[3].length());
Info.Checksum = ~Crc32.Evaluate();
}
public:
template<typename... ArgTypes>
static inline std::string HelperStringFormat(const char* lpszFormat, ArgTypes&& ... Args) {
std::string s(snprintf(nullptr, 0, lpszFormat, std::forward<ArgTypes>(Args)...) + 1, '\x00');
snprintf(s.data(), s.size(), lpszFormat, std::forward<ArgTypes>(Args)...);
while (s.back() == '\x00') {
s.pop_back();
}
return s;
}
static RegisterInfo GenerateRegisterInfo(const char* lpszUserName, const char* lpszLicenseType) {
RegisterInfo RegInfo;
std::string temp;
RegInfo.UserName = lpszUserName;
RegInfo.LicenseType = lpszLicenseType;
temp = GeneratePublicKeySM2CompressedFormat(lpszUserName);
RegInfo.Items[3] = HelperStringFormat("60%.48s", temp.c_str());
RegInfo.Items[0] = GeneratePublicKeySM2CompressedFormat(RegInfo.Items[3].c_str());
RegInfo.UID = HelperStringFormat("%.16s%.4s", temp.c_str() + 48, RegInfo.Items[0].c_str());
while (true) {
auto LicenseTypeSignature = Sign(RegInfo.LicenseType.c_str(), RegInfo.LicenseType.length());
auto LicenseTypeSignatureR = LicenseTypeSignature.r.ToString(16, true);
auto LicenseTypeSignatureS = LicenseTypeSignature.s.ToString(16, true);
if (LicenseTypeSignatureR.length() <= 60 && LicenseTypeSignatureS.length() <= 60) {
RegInfo.Items[1] = HelperStringFormat("60%060s%060s", LicenseTypeSignatureS.c_str(), LicenseTypeSignatureR.c_str());
break;
}
}
temp = RegInfo.UserName + RegInfo.Items[0];
while (true) {
auto UserNameSignature = Sign(temp.c_str(), temp.length());
auto UserNameSignatureR = UserNameSignature.r.ToString(16, true);
auto UserNameSignatureS = UserNameSignature.s.ToString(16, true);
if (UserNameSignatureR.length() <= 60 || UserNameSignatureS.length() <= 60) {
RegInfo.Items[2] = HelperStringFormat("60%060s%060s", UserNameSignatureS.c_str(), UserNameSignatureR.c_str());
break;
}
}
CalculateChecksum(RegInfo);
RegInfo.HexData = HelperStringFormat(
"%zd%zd%zd%zd%s%s%s%s%010lu",
RegInfo.Items[0].length(),
RegInfo.Items[1].length(),
RegInfo.Items[2].length(),
RegInfo.Items[3].length(),
RegInfo.Items[0].c_str(),
RegInfo.Items[1].c_str(),
RegInfo.Items[2].c_str(),
RegInfo.Items[3].c_str(),
RegInfo.Checksum
);
if (RegInfo.HexData.length() % 54 != 0) {
throw std::runtime_error("InternalError: The length of register data is not correct.");
}
return RegInfo;
}
};

74
_tmain.cpp Normal file
View file

@ -0,0 +1,74 @@
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <locale.h>
#include "WinRarConfig.hpp"
#include "WinRarKeygen.hpp"
#include <system_error>
void Help() {
_putts(TEXT("Usage:"));
_putts(TEXT(" winrar-keygen.exe <your name> <license type>"));
_putts(TEXT(""));
_putts(TEXT("Example:"));
_putts(TEXT(""));
_putts(TEXT(" winrar-keygen.exe \"Rebecca Morrison\" \"Single PC usage license\""));
_putts(TEXT(" or:"));
_putts(TEXT(" winrar-keygen.exe \"Rebecca Morrison\" \"Single PC usage license\" > rarreg.key\n"));
}
void PrintRegisterInfo(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info) {
_tprintf_s(TEXT("%hs\n"), "RAR registration data");
_tprintf_s(TEXT("%hs\n"), Info.UserName.c_str());
_tprintf_s(TEXT("%hs\n"), Info.LicenseType.c_str());
_tprintf_s(TEXT("UID=%hs\n"), Info.UID.c_str());
for (size_t i = 0; i < Info.HexData.length(); i += 54) {
_tprintf_s(TEXT("%.54hs\n"), Info.HexData.c_str() + i);
}
}
std::string ToACP(PCWSTR lpszUnicodeString) {
int len;
len = WideCharToMultiByte(CP_ACP, 0, lpszUnicodeString, -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
std::string Result(len, '\x00');
len = WideCharToMultiByte(CP_ACP, 0, lpszUnicodeString, -1, Result.data(), static_cast<int>(Result.length()), NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
while (Result.back() == '\x00') {
Result.pop_back();
}
return Result;
}
int _tmain(int argc, PTSTR argv[]) {
setlocale(LC_ALL, "");
if (argc == 3) {
try {
PrintRegisterInfo(
#if defined(_UNICODE) || defined(UNICODE)
WinRarKeygen<WinRarConfig>::GenerateRegisterInfo(ToACP(argv[1]).c_str(), ToACP(argv[2]).c_str())
#else
WinRarKeygen<WinRarConfig>::GenerateRegisterInfo(argv[1], argv[2])
#endif
);
} catch (std::exception& e) {
_tprintf_s(TEXT("%hs\n"), e.what());
return -1;
}
} else {
Help();
}
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
icon1.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

BIN
icon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
obj/x64-Debug/vc142.idb Normal file

Binary file not shown.

BIN
obj/x64-Debug/vc142.pdb Normal file

Binary file not shown.

View file

@ -0,0 +1,2 @@
 _tmain.cpp
D:\Users\haoning\Documents\Visual Studio 2019\winrar-keygen\BigInteger.hpp(4,10): fatal error C1083: 无法打开包括文件: “gmp.h”: No such file or directory

View file

@ -0,0 +1 @@


View file

@ -0,0 +1,2 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.27.29110:TargetPlatformVersion=10.0.18362.0:
Debug|x64|D:\Users\haoning\Documents\Visual Studio 2019\winrar-keygen\|

BIN
obj/x64-Release/_tmain.obj Normal file

Binary file not shown.

BIN
obj/x64-Release/vc142.pdb Normal file

Binary file not shown.

View file

@ -0,0 +1 @@


View file

@ -0,0 +1,18 @@
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\vc142.pdb
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\_tmain.obj
d:\users\haoning\documents\visual studio 2019\winrar-keygen\bin\x64-release\winrar-keygen.exe
d:\users\haoning\documents\visual studio 2019\winrar-keygen\bin\x64-release\winrar-keygen.pdb
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.res
d:\users\haoning\documents\visual studio 2019\winrar-keygen\bin\x64-release\winrar-keygen.ipdb
d:\users\haoning\documents\visual studio 2019\winrar-keygen\bin\x64-release\winrar-keygen.iobj
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\vcpkg.applocal.log
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\cl.command.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\cl.read.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\cl.write.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\link.command.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\link.read.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\link.write.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\rc.command.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\rc.read.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\rc.write.1.tlog
d:\users\haoning\documents\visual studio 2019\winrar-keygen\obj\x64-release\winrar-keygen.tlog\winrar-keygen.write.1u.tlog

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>D:\Users\haoning\Documents\Visual Studio 2019\winrar-keygen\bin\x64-Release\winrar-keygen.exe</ProjectOutputs>
<ContentFiles></ContentFiles>
<SatelliteDlls></SatelliteDlls>
<NonRecipeFileRefs></NonRecipeFileRefs>
</Project>

View file

@ -0,0 +1,6 @@
 _tmain.cpp
正在生成代码
Previous IPDB not found, fall back to full compilation.
All 409 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
已完成代码的生成
winrar-keygen.vcxproj -> D:\Users\haoning\Documents\Visual Studio 2019\winrar-keygen\bin\x64-Release\winrar-keygen.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,2 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.27.29110:TargetPlatformVersion=10.0.18362.0:
Release|x64|D:\Users\haoning\Documents\Visual Studio 2019\winrar-keygen\|

16
resource.h Normal file
View file

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 winrar-keygen.rc 使用
//
#define IDI_ICON1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

BIN
winrar-keygen.aps Normal file

Binary file not shown.

110
winrar-keygen.rc Normal file
View file

@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "icon1.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "GmbH"
VALUE "FileDescription", "GmbH Keygen Tool"
VALUE "FileVersion", "1.0.0.0"
VALUE "InternalName", "winrar-keygen.exe"
VALUE "LegalCopyright", "Copyright (C) 2020"
VALUE "OriginalFilename", "winrar-k.exe"
VALUE "ProductName", "WinRAR Keygen"
VALUE "ProductVersion", "1.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

31
winrar-keygen.sln Normal file
View file

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrar-keygen", "winrar-keygen.vcxproj", "{2443AA55-9534-4451-9BCC-48AC0982A0CC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Debug|x64.ActiveCfg = Debug|x64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Debug|x64.Build.0 = Debug|x64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Debug|x86.ActiveCfg = Debug|Win32
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Debug|x86.Build.0 = Debug|Win32
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x64.ActiveCfg = Release|x64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x64.Build.0 = Release|x64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x86.ActiveCfg = Release|Win32
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {382D4DCF-4617-437C-B855-01180D3AF852}
EndGlobalSection
EndGlobal

190
winrar-keygen.vcxproj Normal file
View file

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{2443AA55-9534-4451-9BCC-48AC0982A0CC}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>winrarkeygen</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="_tmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BigInteger.hpp" />
<ClInclude Include="Hasher.hpp" />
<ClInclude Include="EllipticCurveGF2m.hpp" />
<ClInclude Include="GaloisField.hpp" />
<ClInclude Include="HasherSha1Traits.hpp" />
<ClInclude Include="resource.h" />
<ClInclude Include="WinRarKeygen.hpp" />
<ClInclude Include="HasherCrc32Traits.hpp" />
<ClInclude Include="WinRarConfig.hpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="winrar-keygen.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="icon1.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="_tmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GaloisField.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="EllipticCurveGF2m.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Hasher.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="HasherCrc32Traits.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="HasherSha1Traits.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="BigInteger.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="WinRarKeygen.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="WinRarConfig.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="winrar-keygen.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="icon1.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>