UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
BigInt.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "HAL/UnrealMemory.h"
9
17template <int32 NumBits, bool bSigned = true>
19{
20public:
21
23
24 static BigInt One;
25
26private:
27
28 enum
29 {
31 BitsPerWord = 32,
32 NumWords = NumBits / BitsPerWord
33 };
34
35 static_assert(NumBits >= 64, "TBigInt must have at least 64 bits.");
36
38 uint32 Bits[NumWords];
39
48 inline static void MakePositiveFactors(BigInt& FactorA, int32& SignA, BigInt& FactorB, int32& SignB)
49 {
50 if (bSigned)
51 {
52 SignA = FactorA.Sign();
53 SignB = FactorB.Sign();
54 if (SignA < 0)
55 {
56 FactorA.Negate();
57 }
58 if (SignB < 0)
59 {
60 FactorB.Negate();
61 }
62 }
63 }
64
72 inline static void RestoreSign(BigInt& Result, int32 SignA, int32 SignB)
73 {
74 if (bSigned && (SignA * SignB) < 0)
75 {
76 Result.Negate();
77 }
78 }
79
80public:
81
83 {
84 return Bits;
85 }
86
88 {
89 return Bits;
90 }
91
94 {
95 FMemory::Memset(Bits, 0, sizeof(Bits));
96 }
97
103 inline void Set(int64 Value)
104 {
105 Zero();
106 Bits[0] = (Value & 0xffffffff);
107 Bits[1] = (Value >> BitsPerWord) & 0xffffffff;
108 }
109
112 {
113 Zero();
114 }
115
122 {
123 Set(Other);
124 }
125
129 [[nodiscard]] explicit TBigInt(const uint32* InBits)
130 {
131 FMemory::Memcpy(Bits, InBits, sizeof(Bits));
132 }
133
138 {
139 // If we weren't given enough data to fill the int, zero first
140 // TODO: Only zero the bits we aren't going to copy over
141 if (InNumBytes < (UE_ARRAY_COUNT(Bits) * sizeof(uint32)))
142 {
143 Zero();
144 }
145
147 }
148
152 [[nodiscard]] explicit TBigInt(const FString& Value)
153 {
154 Parse(Value);
155 }
156
162 void ShiftLeftInternal(const int32 BitCount)
163 {
164 checkSlow(BitCount > 0);
165
166 BigInt Result;
167 if (BitCount & (BitsPerWord - 1))
168 {
169 const int32 LoWordOffset = (BitCount - 1) / BitsPerWord;
170 const int32 HiWordOffset = LoWordOffset + 1;
171 const int32 LoWordShift = BitCount - LoWordOffset * BitsPerWord;
172 const int32 HiWordShift = BitsPerWord - LoWordShift;
173 Result.Bits[NumWords - 1] |= Bits[NumWords - HiWordOffset] << LoWordShift;
174 for (int32 WordIndex = (NumWords - 1) - HiWordOffset; WordIndex >= 0; --WordIndex)
175 {
176 uint32 Value = Bits[WordIndex];
177 Result.Bits[WordIndex + LoWordOffset] |= Value << LoWordShift;
178 Result.Bits[WordIndex + HiWordOffset] |= Value >> HiWordShift;
179 }
180 }
181 else
182 {
183 const int32 ShiftWords = BitCount / BitsPerWord;
184 for (int32 WordIndex = NumWords - 1; WordIndex >= ShiftWords; --WordIndex)
185 {
186 Result.Bits[WordIndex] = Bits[WordIndex - ShiftWords];
187 }
188 }
189 *this = Result;
190 }
191
196 {
197 const int32 HiWordShift = BitsPerWord - 1;
198 Bits[NumWords - 1] = Bits[NumWords - 1] << 1;
199 for (int32 WordIndex = NumWords - 2; WordIndex >= 0; --WordIndex)
200 {
201 const uint32 Value = Bits[WordIndex];
202 Bits[WordIndex + 0] = Value << 1;
203 Bits[WordIndex + 1] |= Value >> HiWordShift;
204 }
205 }
206
212 void ShiftRightInternal(const int32 BitCount)
213 {
214 checkSlow(BitCount > 0);
215
216 BigInt Result;
217 if (BitCount & (BitsPerWord - 1))
218 {
219 const int32 HiWordOffset = (BitCount - 1) / BitsPerWord;
220 const int32 LoWordOffset = HiWordOffset + 1;
221 const int32 HiWordShift = BitCount - HiWordOffset * BitsPerWord;
222 const int32 LoWordShift = BitsPerWord - HiWordShift;
223 Result.Bits[0] |= Bits[HiWordOffset] >> HiWordShift;
224 for (int32 WordIndex = LoWordOffset; WordIndex < NumWords; ++WordIndex)
225 {
226 uint32 Value = Bits[WordIndex];
227 Result.Bits[WordIndex - HiWordOffset] |= Value >> HiWordShift;
228 Result.Bits[WordIndex - LoWordOffset] |= Value << LoWordShift;
229 }
230 }
231 else
232 {
233 const int32 ShiftWords = BitCount / BitsPerWord;
234 for (int32 WordIndex = NumWords - 1; WordIndex >= ShiftWords; --WordIndex)
235 {
236 Result.Bits[WordIndex - ShiftWords] = Bits[WordIndex];
237 }
238 }
239 *this = Result;
240 }
241
246 {
247 const int32 LoWordShift = BitsPerWord - 1;
248 Bits[0] = Bits[0] >> 1;
249 for (int32 WordIndex = 1; WordIndex < NumWords; ++WordIndex)
250 {
251 const uint32 Value = Bits[WordIndex];
252 Bits[WordIndex - 0] = Value >> 1;
253 Bits[WordIndex - 1] |= Value << LoWordShift;
254 }
255 }
256
260 void Add(const BigInt& Other)
261 {
262 int64 CarryOver = 0;
263 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
264 {
265 int64 WordSum = (int64)Other.Bits[WordIndex] + (int64)Bits[WordIndex] + CarryOver;
266 CarryOver = WordSum >> BitsPerWord;
267 WordSum &= 0xffffffff;
268 Bits[WordIndex] = (uint32)WordSum;
269 }
270 }
271
275 void Subtract(const BigInt& Other)
276 {
278 NegativeOther.Negate();
280 }
281
285 [[nodiscard]] bool IsNegative() const
286 {
287 if (bSigned)
288 {
289 return !!(Bits[NumWords - 1] & (1U << (BitsPerWord - 1)));
290 }
291 else
292 {
293 return false;
294 }
295 }
296
300 [[nodiscard]] int32 Sign() const
301 {
302 return IsNegative() ? -1 : 1;
303 }
304
308 void Negate()
309 {
310 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
311 {
312 Bits[WordIndex] = ~Bits[WordIndex];
313 }
314 Add(One);
315 }
316
321 {
322 int32 WordIndex;
323 for (WordIndex = NumWords - 1; WordIndex >= 0 && Bits[WordIndex] == 0; --WordIndex);
324 return WordIndex;
325 }
326
330 void MultiplyFast(const BigInt& Factor)
331 {
332 const int64 Base = 2LL << BitsPerWord;
333 TBigInt<NumBits * 2, bSigned> Result; // Twice as many bits for overflow protection
334 uint32* ResultBits = Result.GetBits();
335 BigInt Temp = *this;
336
337 const int32 NumWordsA = Temp.GetHighestNonZeroWord() + 1;
338 const int32 NumWordsB = Factor.GetHighestNonZeroWord() + 1;
339
341 {
342 const uint64 A = Temp.Bits[WordIndexA];
343 uint64 Carry = 0;
345 {
346 const uint64 B = Factor.Bits[WordIndexB];
347 const uint64 Product = ResultBits[WordIndexA + WordIndexB] + Carry + A * B;
348 Carry = Product >> BitsPerWord;
349 ResultBits[WordIndexA + WordIndexB] = (uint32)(Product & (Base - 1));
350 }
352 }
353
354 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
355 {
356 Bits[WordIndex] = ResultBits[WordIndex];
357 }
358 }
359
363 void Multiply(const BigInt& Factor)
364 {
365 BigInt Result = *this;
366 BigInt Other = Factor;
367
370 MakePositiveFactors(Result, ResultSign, Other, OtherSign);
371
372 Result.MultiplyFast(Other);
373
374 // Restore the sign if necessary
375 RestoreSign(Result, OtherSign, ResultSign);
376 *this = Result;
377 }
378
382 void DivideWithRemainder(const BigInt& Divisor, BigInt& Remainder)
383 {
384 BigInt Denominator(Divisor);
385 BigInt Dividend(*this);
386
389 MakePositiveFactors(Denominator, DenominatorSign, Dividend, DividendSign);
390
391 if (Denominator > Dividend)
392 {
393 Remainder = *this;
394 Zero();
395 return;
396 }
397 if (Denominator == Dividend)
398 {
399 Remainder.Zero();
400 *this = One;
401 RestoreSign(*this, DenominatorSign, DividendSign);
402 return;
403 }
404
407
409
410 if (ShiftCount > 0)
411 {
412 Denominator.ShiftLeftInternal(ShiftCount);
413 }
414
415 while (Denominator <= Dividend)
416 {
417 Denominator.ShiftLeftByOneInternal();
418 ShiftCount++;
419 }
420
421 Denominator.ShiftRightByOneInternal();
422
423 ShiftCount--; // equivalent of a shift right
424 if (ShiftCount)
425 {
426 Current.ShiftLeftInternal(ShiftCount);
427 }
428
429 // Reuse ShiftCount to track number of pending shifts
430 ShiftCount = 0;
431 const int32 NumLoops = Current.GetHighestNonZeroBit() + 1;
432
433 for (int32 i = 0; i < NumLoops; ++i)
434 {
435 if (Dividend >= Denominator)
436 {
437 if (ShiftCount != 0)
438 {
439 Current.ShiftRightInternal(ShiftCount);
440 ShiftCount = 0;
441 }
442
443 Dividend -= Denominator;
444 Quotient |= Current;
445 }
446 Denominator.ShiftRightByOneInternal();
447 ShiftCount++;
448 }
450 Remainder = Dividend;
451 *this = Quotient;
452 }
453
457 void Divide(const BigInt& Divisor)
458 {
459 BigInt Remainder;
460 DivideWithRemainder(Divisor, Remainder);
461 }
462
466 void Modulo(const BigInt& Modulus)
467 {
468 // a mod b = a - floor(a/b)*b
469 check(!IsNegative());
470 BigInt Dividend(*this);
471
472 // Dividend.Divide(Modulus);
473 BigInt Temp;
474 Dividend.DivideWithRemainder(Modulus, Temp);
475 Dividend.MultiplyFast(Modulus);
476
477 // Subtract(Dividend);
478 Dividend.Negate();
479 Add(Dividend);
480 }
481
485 void Sqrt()
486 {
487 BigInt Number(*this);
488 BigInt Result;
489
490 BigInt Bit(1);
491 Bit.ShiftLeftInternal(NumBits - 2);
492 while (Bit > Number)
493 {
494 Bit.ShiftRightInternal(2);
495 }
496
497 BigInt Temp;
498 while (!Bit.IsZero())
499 {
500 Temp = Result;
501 Temp.Add(Bit);
502 if (Number >= Temp)
503 {
504 Number -= Temp;
505 Result.ShiftRightInternal(1);
506 Result += Bit;
507 }
508 else
509 {
510 Result.ShiftRightInternal(1);
511 }
512 Bit.ShiftRightInternal(2);
513 }
514 *this = Result;
515 }
516
521 {
522 Set(Other);
523 return *this;
524 }
525
530 {
531 for (int32 WordIndex = NumWords - 1; WordIndex >= 0; --WordIndex)
532 {
533 if (!!Bits[WordIndex])
534 {
535 int32 BitIndex;
536 for (BitIndex = BitsPerWord - 1; BitIndex >= 0 && !(Bits[WordIndex] & (1 << BitIndex)); --BitIndex);
537 return BitIndex + WordIndex * BitsPerWord;
538 }
539 }
540 return -1;
541 }
542
546 [[nodiscard]] int32 GetBit(int32 BitIndex) const
547 {
548 const int32 WordIndex = BitIndex / BitsPerWord;
549 BitIndex -= WordIndex * BitsPerWord;
550 return (Bits[WordIndex] & (1 << BitIndex)) ? 1 : 0;
551 }
552
556 void SetBit(int32 BitIndex, int32 Value)
557 {
558 const int32 WordIndex = BitIndex / BitsPerWord;
559 BitIndex -= WordIndex * BitsPerWord;
560 if (!!Value)
561 {
562 Bits[WordIndex] |= (1 << BitIndex);
563 }
564 else
565 {
566 Bits[WordIndex] &= ~(1 << BitIndex);
567 }
568 }
569
575 void ShiftLeft(const int32 BitCount)
576 {
577 // Early out in the trivial cases
578 if (BitCount == 0)
579 {
580 return;
581 }
582 else if (BitCount < 0)
583 {
584 ShiftRight(-BitCount);
585 return;
586 }
587 else if (BitCount >= NumBits)
588 {
589 Zero();
590 return;
591 }
592 ShiftLeftInternal(BitCount);
593 }
594
600 void ShiftRight(const int32 BitCount)
601 {
602 // Early out in the trivial cases
603 if (BitCount == 0)
604 {
605 return;
606 }
607 else if (BitCount < 0)
608 {
609 ShiftLeft(-BitCount);
610 return;
611 }
612 else if (BitCount >= NumBits)
613 {
614 Zero();
615 return;
616 }
617 ShiftRightInternal(BitCount);
618 }
619
623 void BitwiseOr(const BigInt& Other)
624 {
625 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
626 {
627 Bits[WordIndex] |= Other.Bits[WordIndex];
628 }
629 }
630
635 {
636 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
637 {
638 Bits[WordIndex] &= Other.Bits[WordIndex];
639 }
640 }
641
646 {
647 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
648 {
649 Bits[WordIndex] = ~Bits[WordIndex];
650 }
651 }
652
656 [[nodiscard]] bool IsEqual(const BigInt& Other) const
657 {
658 for (int32 WordIndex = 0; WordIndex < NumWords; ++WordIndex)
659 {
660 if (Bits[WordIndex] != Other.Bits[WordIndex])
661 {
662 return false;
663 }
664 }
665
666 return true;
667 }
668
672 [[nodiscard]] bool IsLess(const BigInt& Other) const
673 {
674 if (IsNegative())
675 {
676 if (!Other.IsNegative())
677 {
678 return true;
679 }
680 else
681 {
682 return IsGreater(Other);
683 }
684 }
685 int32 WordIndex;
686 for (WordIndex = NumWords - 1; WordIndex >= 0 && Other.Bits[WordIndex] == Bits[WordIndex]; --WordIndex);
687 return WordIndex >= 0 && Bits[WordIndex] < Other.Bits[WordIndex];
688 }
689
693 [[nodiscard]] bool IsLessOrEqual(const BigInt& Other) const
694 {
695 if (IsNegative())
696 {
697 if (!Other.IsNegative())
698 {
699 return true;
700 }
701 else
702 {
703 return IsGreaterOrEqual(Other);
704 }
705 }
706 int32 WordIndex;
707 for (WordIndex = NumWords - 1; WordIndex >= 0 && Other.Bits[WordIndex] == Bits[WordIndex]; --WordIndex);
708 return WordIndex < 0 || Bits[WordIndex] < Other.Bits[WordIndex];
709 }
710
714 [[nodiscard]] bool IsGreater(const BigInt& Other) const
715 {
716 if (IsNegative())
717 {
718 if (!Other.IsNegative())
719 {
720 return false;
721 }
722 else
723 {
724 return IsLess(Other);
725 }
726 }
727 int32 WordIndex;
728 for (WordIndex = NumWords - 1; WordIndex >= 0 && Other.Bits[WordIndex] == Bits[WordIndex]; --WordIndex);
729 return WordIndex >= 0 && Bits[WordIndex] > Other.Bits[WordIndex];
730 }
731
735 [[nodiscard]] bool IsGreaterOrEqual(const BigInt& Other) const
736 {
737 if (IsNegative())
738 {
739 if (Other.IsNegative())
740 {
741 return false;
742 }
743 else
744 {
745 return IsLessOrEqual(Other);
746 }
747 }
748 int32 WordIndex;
749 for (WordIndex = NumWords - 1; WordIndex >= 0 && Other.Bits[WordIndex] == Bits[WordIndex]; --WordIndex);
750 return WordIndex < 0 || Bits[WordIndex] > Other.Bits[WordIndex];
751 }
752
756 [[nodiscard]] bool IsZero() const
757 {
758 int32 WordIndex;
759 for (WordIndex = NumWords - 1; WordIndex >= 0 && !Bits[WordIndex]; --WordIndex);
760 return WordIndex < 0;
761 }
762
767 {
768 return !IsNegative() && !IsZero();
769 }
770
774 [[nodiscard]] bool IsLessThanZero() const
775 {
776 return IsNegative() && !IsZero();
777 }
778
779 [[nodiscard]] bool IsFirstBitSet() const
780 {
781 return !!(Bits[0] & 1);
782 }
786 [[nodiscard]] bool operator[](int32 BitIndex) const
787 {
788 return GetBit(BitIndex);
789 }
790
791 // Begin operator overloads
793 {
794 BigInt Result = *this;
795 Result.ShiftRight(Count);
796 return Result;
797 }
798
800 {
802 return *this;
803 }
804
806 {
807 BigInt Result = *this;
808 Result.ShiftLeft(Count);
809 return Result;
810 }
811
813 {
815 return *this;
816 }
817
819 {
820 BigInt Result(*this);
821 Result.Add(Other);
822 return Result;
823 }
824
826 {
827 Add(One);
828 return *this;
829 }
830
832 {
833 Add(Other);
834 return *this;
835 }
836
838 {
839 BigInt Result(*this);
840 Result.Subtract(Other);
841 return Result;
842 }
843
845 {
846 Subtract(One);
847 return *this;
848 }
849
851 {
853 return *this;
854 }
855
857 {
858 BigInt Result(*this);
859 Result.Multiply(Other);
860 return Result;
861 }
862
864 {
866 return *this;
867 }
868
870 {
871 BigInt Result(*this);
872 Result.Divide(Divider);
873 return Result;
874 }
875
877 {
879 return *this;
880 }
881
882 [[nodiscard]] BigInt operator%(const BigInt& Modulus) const
883 {
884 BigInt Result(*this);
885 Result.Modulo(Modulus);
886 return Result;
887 }
888
889 BigInt& operator%=(const BigInt& Modulus)
890 {
891 Modulo(Modulus);
892 return *this;
893 }
894
895 [[nodiscard]] bool operator<(const BigInt& Other) const
896 {
897 return IsLess(Other);
898 }
899
900 [[nodiscard]] bool operator<=(const BigInt& Other) const
901 {
902 return IsLessOrEqual(Other);
903 }
904
905 [[nodiscard]] bool operator>(const BigInt& Other) const
906 {
907 return IsGreater(Other);
908 }
909
910 [[nodiscard]] bool operator>=(const BigInt& Other) const
911 {
912 return IsGreaterOrEqual(Other);
913 }
914
915 [[nodiscard]] bool operator==(const BigInt& Other) const
916 {
917 return IsEqual(Other);
918 }
919
920 [[nodiscard]] bool operator!=(const BigInt& Other) const
921 {
922 return !IsEqual(Other);
923 }
924
926 {
927 BigInt Result(*this);
928 Result.BitwiseAnd(Other);
929 return Result;
930 }
931
933 {
935 return *this;
936 }
937
939 {
940 BigInt Result(*this);
941 Result.BitwiseOr(Other);
942 return Result;
943 }
944
946 {
948 return *this;
949 }
950
952 {
953 BigInt Result(*this);
954 Result.BitwiseNot();
955 return Result;
956 }
957 // End operator overloads
958
963 {
964 return (int64)Bits[0] + ((int64)Bits[1] << BitsPerWord);
965 }
966
970 [[nodiscard]] FString ToString() const
971 {
972 FString Text(TEXT("0x"));
973 int32 WordIndex;
974 for (WordIndex = NumWords - 1; WordIndex > 0; --WordIndex)
975 {
976 if (Bits[WordIndex])
977 {
978 break;
979 }
980 }
981 for (; WordIndex >= 0; --WordIndex)
982 {
983 Text += FString::Printf(TEXT("%08x"), Bits[WordIndex]);
984 }
985 return Text;
986 }
987
991 void Parse(const FString& Value)
992 {
993 Zero();
995 if (Value.Len() >= 2 && Value[0] == '0' && FChar::ToUpper(Value[1]) == 'X')
996 {
997 ValueStartIndex = 2;
998 }
999 check((Value.Len() - ValueStartIndex) <= (NumBits / 4));
1000 const int32 NybblesPerWord = BitsPerWord / 4;
1001 for (int32 CharIndex = Value.Len() - 1; CharIndex >= ValueStartIndex; --CharIndex)
1002 {
1003 const TCHAR ByteChar = Value[CharIndex];
1004 const int32 ByteIndex = (Value.Len() - CharIndex - 1);
1005 const int32 WordIndex = ByteIndex / NybblesPerWord;
1006 const int32 ByteValue = ByteChar > '9' ? (FChar::ToUpper(ByteChar) - 'A' + 10) : (ByteChar - '0');
1007 check(ByteValue >= 0 && ByteValue <= 15);
1008 Bits[WordIndex] |= (ByteValue << (ByteIndex % NybblesPerWord) * 4);
1009 }
1010 }
1011
1016 {
1017 for (int32 Index = 0; Index < NumWords; ++Index)
1018 {
1019 Ar << Value.Bits[Index];
1020 }
1021 return Ar;
1022 }
1023};
1024
1025template<int32 NumBits, bool bSigned>
1027
1028// Predefined big int types
1032
1036template <typename IntType>
1038{
1039 IntType Exponent;
1040 IntType Modulus;
1041};
1043
1048{
1052 template <typename IntType>
1053 IntType CalculateGCD(IntType ValueA, IntType ValueB)
1054 {
1055 // Early out in obvious cases
1056 if (ValueA == 0)
1057 {
1058 return ValueA;
1059 }
1060 if (ValueB == 0)
1061 {
1062 return ValueB;
1063 }
1064
1065 // Shift is log(n) where n is the greatest power of 2 dividing both A and B.
1066 int32 Shift;
1067 for (Shift = 0; ((ValueA | ValueB) & 1) == 0; ++Shift)
1068 {
1069 ValueA >>= 1;
1070 ValueB >>= 1;
1071 }
1072
1073 while ((ValueA & 1) == 0)
1074 {
1075 ValueA >>= 1;
1076 }
1077
1078 do
1079 {
1080 // Remove all factors of 2 in B.
1081 while ((ValueB & 1) == 0)
1082 {
1083 ValueB >>= 1;
1084 }
1085
1086 // Make sure A <= B
1087 if (ValueA > ValueB)
1088 {
1089 Swap(ValueA, ValueB);
1090 }
1091 ValueB = ValueB - ValueA;
1092 }
1093 while (ValueB != 0);
1094
1095 // Restore common factors of 2.
1096 return ValueA << Shift;
1097 }
1098
1105 template <typename IntType>
1106 IntType CalculateMultiplicativeInverseOfExponent(IntType Exponent, IntType Totient)
1107 {
1108 IntType x0 = 1;
1109 IntType y0 = 0;
1110 IntType x1 = 0;
1111 IntType y1 = 1;
1112 IntType a0 = Exponent;
1113 IntType b0 = Totient;
1114 while (b0 != 0)
1115 {
1116 // Quotient = Exponent / Totient
1117 IntType Quotient = a0 / b0;
1118
1119 // (Exponent, Totient) = (Totient, Exponent mod Totient)
1120 IntType b1 = a0 % b0;
1121 a0 = b0;
1122 b0 = b1;
1123
1124 // (x, lastx) = (lastx - Quotient*x, x)
1125 IntType x2 = x0 - Quotient * x1;
1126 x0 = x1;
1127 x1 = x2;
1128
1129 // (y, lasty) = (lasty - Quotient*y, y)
1130 IntType y2 = y0 - Quotient * y1;
1131 y0 = y1;
1132 y1 = y2;
1133 }
1134 // If x0 is negative, find the corresponding positive element in (mod Totient)
1135 while (x0 < 0)
1136 {
1137 x0 += Totient;
1138 }
1139 return x0;
1140 }
1141
1145 template <typename IntType>
1146 void GenerateKeyPair(const IntType& P, const IntType& Q, FEncryptionKey& PublicKey, FEncryptionKey& PrivateKey)
1147 {
1148 const IntType Modulus = P * Q;
1149 const IntType Fi = (P - 1) * (Q - 1);
1150
1151 IntType EncodeExponent = Fi;
1152 IntType DecodeExponent = 0;
1153 do
1154 {
1157 }
1158 while (DecodeExponent == EncodeExponent);
1159
1160 PublicKey.Exponent = DecodeExponent;
1161 PublicKey.Modulus = Modulus;
1162
1163 PrivateKey.Exponent = EncodeExponent;
1164 PrivateKey.Modulus = Modulus;
1165 }
1166
1170 template <typename IntType>
1171 IntType ModularPow(IntType Base, IntType Exponent, IntType Modulus)
1172 {
1173 const IntType One(1);
1174 IntType Result(1);
1175 while (Exponent > 0)
1176 {
1177 if (Exponent.IsFirstBitSet())
1178 {
1179 Result = (Result * Base) % Modulus;
1180 }
1181 Exponent >>= 1;
1182 Base = (Base * Base) % Modulus;
1183 }
1184 return Result;
1185 }
1186
1190 template <typename IntType>
1191 void EncryptBytes(IntType* EncryptedData, const uint8* Data, const int64 DataLength, const FEncryptionKey& EncryptionKey)
1192 {
1193 for (int Index = 0; Index < DataLength; ++Index)
1194 {
1195 EncryptedData[Index] = FEncryption::ModularPow(IntType(Data[Index]), EncryptionKey.Exponent, EncryptionKey.Modulus);
1196 }
1197 }
1198
1202 template <typename IntType>
1203 void DecryptBytes(uint8* DecryptedData, const IntType* Data, const int64 DataLength, const FEncryptionKey& DecryptionKey)
1204 {
1205 for (int64 Index = 0; Index < DataLength; ++Index)
1206 {
1207 IntType DecryptedByte = FEncryption::ModularPow(Data[Index], DecryptionKey.Exponent, DecryptionKey.Modulus);
1209 }
1210 }
1211}
1212
1214
1218template <>
1220{
1222 while (Exponent.IsGreaterThanZero())
1223 {
1224 if (Exponent.IsFirstBitSet())
1225 {
1226 Result.MultiplyFast(Base);
1227 Result.Modulo(Modulus);
1228 }
1229 Exponent.ShiftRightByOneInternal();
1230 Base.MultiplyFast(Base);
1231 Base.Modulo(Modulus);
1232 }
1233 return Result;
1234}
1235
1237
1238template <class InDataType>
1240{
1242
1244
1246 {
1247 Data = 0;
1248 }
1249
1251 {
1252 Ar << Data;
1253 }
1254
1255 static int64 Size()
1256 {
1257 return sizeof(InDataType);
1258 }
1259
1260 bool IsValid() const
1261 {
1262 return Data != 0;
1263 }
1264
1266 {
1267 return Data != InOther.Data;
1268 }
1269
1271 {
1272 return Data == InOther.Data;
1273 }
1274
1279 {
1280 Value.Serialize(Ar);
1281 return Ar;
1282 }
1283};
1284
1285struct FEncryptedSignature : public FSignatureBase<TEncryptionInt>
1286{
1287
1288};
1289
1291{
1292
1293};
1294
1295namespace FEncryption
1296{
1301
1306}
1307
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
TBigInt< 512 > TEncryptionInt
Definition BigInt.h:1031
TBigInt< 512 > int512
Definition BigInt.h:1030
TBigInt< 256 > int256
Definition BigInt.h:1029
TEncryptionKey< TEncryptionInt > FEncryptionKey
Definition BigInt.h:1042
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ One
Definition PropertyPathHelpersTest.h:16
#define UE_ARRAY_COUNT(array)
Definition UnrealTemplate.h:212
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
virtual void Serialize(void *V, int64 Length)
Definition Archive.h:1689
Definition BigInt.h:19
bool operator!=(const BigInt &Other) const
Definition BigInt.h:920
void ShiftRightByOneInternal()
Definition BigInt.h:245
bool IsEqual(const BigInt &Other) const
Definition BigInt.h:656
bool IsZero() const
Definition BigInt.h:756
BigInt operator<<(int32 Count) const
Definition BigInt.h:805
bool IsFirstBitSet() const
Definition BigInt.h:779
bool operator[](int32 BitIndex) const
Definition BigInt.h:786
bool IsNegative() const
Definition BigInt.h:285
void ShiftLeftByOneInternal()
Definition BigInt.h:195
bool IsGreater(const BigInt &Other) const
Definition BigInt.h:714
BigInt operator*(const BigInt &Other) const
Definition BigInt.h:856
FString ToString() const
Definition BigInt.h:970
BigInt operator>>(int32 Count) const
Definition BigInt.h:792
BigInt & operator&=(const BigInt &Other)
Definition BigInt.h:932
bool IsGreaterOrEqual(const BigInt &Other) const
Definition BigInt.h:735
UE_FORCEINLINE_HINT void Zero()
Definition BigInt.h:93
bool operator==(const BigInt &Other) const
Definition BigInt.h:915
BigInt operator+(const BigInt &Other) const
Definition BigInt.h:818
int32 GetHighestNonZeroWord() const
Definition BigInt.h:320
BigInt & operator/=(const BigInt &Divider)
Definition BigInt.h:876
void SetBit(int32 BitIndex, int32 Value)
Definition BigInt.h:556
bool operator<=(const BigInt &Other) const
Definition BigInt.h:900
BigInt & operator-=(const BigInt &Other)
Definition BigInt.h:850
static BigInt One
Definition BigInt.h:24
TBigInt(const uint8 *InData, uint32 InNumBytes)
Definition BigInt.h:137
TBigInt()
Definition BigInt.h:111
void Multiply(const BigInt &Factor)
Definition BigInt.h:363
int64 ToInt() const
Definition BigInt.h:962
BigInt operator|(const BigInt &Other) const
Definition BigInt.h:938
void Subtract(const BigInt &Other)
Definition BigInt.h:275
TBigInt & operator=(int64 Other)
Definition BigInt.h:520
void Set(int64 Value)
Definition BigInt.h:103
BigInt & operator|=(const BigInt &Other)
Definition BigInt.h:945
bool IsLessOrEqual(const BigInt &Other) const
Definition BigInt.h:693
bool operator>(const BigInt &Other) const
Definition BigInt.h:905
UE_FORCEINLINE_HINT uint32 * GetBits()
Definition BigInt.h:82
BigInt & operator--()
Definition BigInt.h:844
BigInt operator-(const BigInt &Other) const
Definition BigInt.h:837
BigInt & operator*=(const BigInt &Other)
Definition BigInt.h:863
void ShiftRight(const int32 BitCount)
Definition BigInt.h:600
void ShiftRightInternal(const int32 BitCount)
Definition BigInt.h:212
void MultiplyFast(const BigInt &Factor)
Definition BigInt.h:330
BigInt & operator<<=(int32 Count)
Definition BigInt.h:812
void ShiftLeftInternal(const int32 BitCount)
Definition BigInt.h:162
int32 Sign() const
Definition BigInt.h:300
UE_FORCEINLINE_HINT const uint32 * GetBits() const
Definition BigInt.h:87
void BitwiseNot()
Definition BigInt.h:645
TBigInt(const FString &Value)
Definition BigInt.h:152
BigInt operator~() const
Definition BigInt.h:951
bool operator<(const BigInt &Other) const
Definition BigInt.h:895
TBigInt(const uint32 *InBits)
Definition BigInt.h:129
void ShiftLeft(const int32 BitCount)
Definition BigInt.h:575
void BitwiseAnd(const BigInt &Other)
Definition BigInt.h:634
bool IsGreaterThanZero() const
Definition BigInt.h:766
int32 GetBit(int32 BitIndex) const
Definition BigInt.h:546
BigInt operator%(const BigInt &Modulus) const
Definition BigInt.h:882
BigInt operator/(const BigInt &Divider) const
Definition BigInt.h:869
void Modulo(const BigInt &Modulus)
Definition BigInt.h:466
void DivideWithRemainder(const BigInt &Divisor, BigInt &Remainder)
Definition BigInt.h:382
TBigInt(int64 Other)
Definition BigInt.h:121
void BitwiseOr(const BigInt &Other)
Definition BigInt.h:623
void Add(const BigInt &Other)
Definition BigInt.h:260
BigInt & operator>>=(int32 Count)
Definition BigInt.h:799
TBigInt< NumBits, bSigned > BigInt
Definition BigInt.h:22
void Parse(const FString &Value)
Definition BigInt.h:991
BigInt operator&(const BigInt &Other) const
Definition BigInt.h:925
int32 GetHighestNonZeroBit() const
Definition BigInt.h:529
bool IsLessThanZero() const
Definition BigInt.h:774
BigInt & operator+=(const BigInt &Other)
Definition BigInt.h:831
void Divide(const BigInt &Divisor)
Definition BigInt.h:457
friend FArchive & operator<<(FArchive &Ar, BigInt &Value)
Definition BigInt.h:1015
BigInt & operator++()
Definition BigInt.h:825
BigInt & operator%=(const BigInt &Modulus)
Definition BigInt.h:889
void Sqrt()
Definition BigInt.h:485
bool operator>=(const BigInt &Other) const
Definition BigInt.h:910
void Negate()
Definition BigInt.h:308
bool IsLess(const BigInt &Other) const
Definition BigInt.h:672
Definition BigInt.h:1048
IntType CalculateMultiplicativeInverseOfExponent(IntType Exponent, IntType Totient)
Definition BigInt.h:1106
IntType ModularPow(IntType Base, IntType Exponent, IntType Modulus)
Definition BigInt.h:1171
void GenerateKeyPair(const IntType &P, const IntType &Q, FEncryptionKey &PublicKey, FEncryptionKey &PrivateKey)
Definition BigInt.h:1146
IntType CalculateGCD(IntType ValueA, IntType ValueB)
Definition BigInt.h:1053
void EncryptSignature(const FDecryptedSignature &InUnencryptedSignature, FEncryptedSignature &OutEncryptedSignature, const FEncryptionKey &EncryptionKey)
Definition BigInt.h:1297
void DecryptSignature(const FEncryptedSignature &InEncryptedSignature, FDecryptedSignature &OutUnencryptedSignature, const FEncryptionKey &EncryptionKey)
Definition BigInt.h:1302
void EncryptBytes(IntType *EncryptedData, const uint8 *Data, const int64 DataLength, const FEncryptionKey &EncryptionKey)
Definition BigInt.h:1191
void DecryptBytes(uint8 *DecryptedData, const IntType *Data, const int64 DataLength, const FEncryptionKey &DecryptionKey)
Definition BigInt.h:1203
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
U16 Index
Definition radfft.cpp:71
Definition BigInt.h:1291
Definition BigInt.h:1286
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119
Definition BigInt.h:1240
FSignatureBase()
Definition BigInt.h:1245
bool operator==(const FSignatureBase &InOther)
Definition BigInt.h:1270
bool operator!=(const FSignatureBase &InOther)
Definition BigInt.h:1265
friend FArchive & operator<<(FArchive &Ar, FSignatureBase &Value)
Definition BigInt.h:1278
DataType Data
Definition BigInt.h:1243
void Serialize(FArchive &Ar)
Definition BigInt.h:1250
bool IsValid() const
Definition BigInt.h:1260
static int64 Size()
Definition BigInt.h:1255
InDataType DataType
Definition BigInt.h:1241
static CharType ToUpper(CharType Char)
Definition Char.h:80
Definition BigInt.h:1038
IntType Modulus
Definition BigInt.h:1040
IntType Exponent
Definition BigInt.h:1039