Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
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"
6#include "Misc/AssertionMacros.h"
7#include "HAL/UnrealMemory.h"
8#include "Containers/UnrealString.h"
9
10/**
11 * n-bit integer. @todo: optimize
12 * Data is stored as an array of 32-bit words from the least to the most significant
13 * Doesn't handle overflows (not a big issue, we can always use a bigger bit count)
14 * Minimum sanity checks.
15 * Can convert from int64 and back (by truncating the result, this is mostly for testing)
16 */
17template <int32 NumBits, bool bSigned = true>
19{
20public:
21
22 typedef TBigInt<NumBits, bSigned> BigInt;
23
24 static BigInt One;
25
26private:
27
28 enum
29 {
30 /** Word size. */
32 NumWords = NumBits / BitsPerWord
33 };
34
35 static_assert(NumBits >= 64, "TBigInt must have at least 64 bits.");
36
37 /** All bits stored as an array of words. */
38 uint32 Bits[NumWords];
39
40 /**
41 * Makes sure both factors are positive integers and stores their original signs
42 *
43 * @param FactorA first factor
44 * @param SignA sign of the first factor
45 * @param FactorB second factor
46 * @param SignB sign of the second pactor
47 */
48 FORCEINLINE 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 {
57 }
58 if (SignB < 0)
59 {
61 }
62 }
63 }
64
65 /**
66 * Restores a sign of a result based on the sign of two factors that produced the result.
67 *
68 * @param Result math opration result
69 * @param SignA sign of the first factor
70 * @param SignB sign of the second factor
71 */
72 FORCEINLINE 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
87 FORCEINLINE const uint32* GetBits() const
88 {
89 return Bits;
90 }
91
92 /** Sets this integer to 0. */
94 {
95 FMemory::Memset(Bits, 0, sizeof(Bits));
96 }
97
98 /**
99 * Initializes this big int with a 64 bit integer value.
100 *
101 * @param Value The value to set.
102 */
103 FORCEINLINE void Set(int64 Value)
104 {
105 Zero();
106 Bits[0] = (Value & 0xffffffff);
107 Bits[1] = (Value >> BitsPerWord) & 0xffffffff;
108 }
109
110 /** Default constructor. Initializes the number to zero. */
112 {
113 Zero();
114 }
115
116 /**
117 * Constructor. Initializes this big int with a 64 bit integer value.
118 *
119 * @param Other The value to set.
120 */
121 TBigInt(int64 Other)
122 {
123 Set(Other);
124 }
125
126 /**
127 * Constructor. Initializes this big int with an array of words.
128 */
129 explicit TBigInt(const uint32* InBits)
130 {
131 FMemory::Memcpy(Bits, InBits, sizeof(Bits));
132 }
133
134 /**
135 * Constructor. Initializes this big int with an array of bytes.
136 */
137 explicit TBigInt(const uint8* InData, uint32 InNumBytes)
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
149 /**
150 * Constructor. Initializes this big int with a string representing a hex value.
151 */
152 explicit TBigInt(const FString& Value)
153 {
154 Parse(Value);
155 }
156
157 /**
158 * Shift left by the specified amount of bits. Does not check if BitCount is valid.
159 *
160 * @param BitCount the number of bits to shift.
161 */
162 void ShiftLeftInternal(const int32 BitCount)
163 {
164 checkSlow(BitCount > 0);
165
167 if (BitCount & (BitsPerWord - 1))
168 {
169 const int32 LoWordOffset = (BitCount - 1) / BitsPerWord;
170 const int32 HiWordOffset = LoWordOffset + 1;
174 for (int32 WordIndex = (NumWords - 1) - HiWordOffset; WordIndex >= 0; --WordIndex)
175 {
179 }
180 }
181 else
182 {
185 {
187 }
188 }
189 *this = Result;
190 }
191
192 /**
193 * Shift left by 1 bit.
194 */
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
207 /**
208 * Shift right by the specified amount of bits. Does not check if BitCount is valid.
209 *
210 * @param BitCount the number of bits to shift.
211 */
212 void ShiftRightInternal(const int32 BitCount)
213 {
214 checkSlow(BitCount > 0);
215
217 if (BitCount & (BitsPerWord - 1))
218 {
219 const int32 HiWordOffset = (BitCount - 1) / BitsPerWord;
220 const int32 LoWordOffset = HiWordOffset + 1;
225 {
229 }
230 }
231 else
232 {
235 {
237 }
238 }
239 *this = Result;
240 }
241
242 /**
243 * Shift right by 1 bit.
244 */
246 {
247 const int32 LoWordShift = BitsPerWord - 1;
248 Bits[0] = Bits[0] >> 1;
250 {
251 const uint32 Value = Bits[WordIndex];
252 Bits[WordIndex - 0] = Value >> 1;
253 Bits[WordIndex - 1] |= Value << LoWordShift;
254 }
255 }
256
257 /**
258 * Adds two integers.
259 */
260 void Add(const BigInt& Other)
261 {
262 int64 CarryOver = 0;
264 {
267 WordSum &= 0xffffffff;
269 }
270 }
271
272 /**
273 * Subtracts two integers.
274 */
275 void Subtract(const BigInt& Other)
276 {
280 }
281
282 /**
283 * Checks if this integer is negative.
284 */
285 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
297 /**
298 * Returns the sign of this integer.
299 */
300 int32 Sign() const
301 {
302 return IsNegative() ? -1 : 1;
303 }
304
305 /**
306 * Negates this integer. value = -value
307 */
308 void Negate()
309 {
311 {
313 }
314 Add(One);
315 }
316
317 /**
318 * Returns the index of the highest word that is not zero. -1 if no such word exists.
319 */
321 {
323 for (WordIndex = NumWords - 1; WordIndex >= 0 && Bits[WordIndex] == 0; --WordIndex);
324 return WordIndex;
325 }
326
327 /**
328 * Multiplies two positive integers.
329 */
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
335 BigInt Temp = *this;
336
339
341 {
342 const uint64 A = Temp.Bits[WordIndexA];
343 uint64 Carry = 0;
345 {
346 const uint64 B = Factor.Bits[WordIndexB];
350 }
352 }
353
355 {
357 }
358 }
359
360 /**
361 * Multiplies two integers.
362 */
363 void Multiply(const BigInt& Factor)
364 {
365 BigInt Result = *this;
367
371
373
374 // Restore the sign if necessary
376 *this = Result;
377 }
378
379 /**
380 * Divides two integers with remainder.
381 */
382 void DivideWithRemainder(const BigInt& Divisor, BigInt& Remainder)
383 {
385 BigInt Dividend(*this);
386
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;
402 return;
403 }
404
407
409
410 if (ShiftCount > 0)
411 {
413 }
414
415 while (Denominator <= Dividend)
416 {
418 ShiftCount++;
419 }
420
422
423 ShiftCount--; // equivalent of a shift right
424 if (ShiftCount)
425 {
427 }
428
429 // Reuse ShiftCount to track number of pending shifts
430 ShiftCount = 0;
432
433 for (int32 i = 0; i < NumLoops; ++i)
434 {
435 if (Dividend >= Denominator)
436 {
437 if (ShiftCount != 0)
438 {
440 ShiftCount = 0;
441 }
442
444 Quotient |= Current;
445 }
447 ShiftCount++;
448 }
451 *this = Quotient;
452 }
453
454 /**
455 * Divides two integers.
456 */
457 void Divide(const BigInt& Divisor)
458 {
461 }
462
463 /**
464 * Performs modulo operation on this integer.
465 */
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;
476
477 // Subtract(Dividend);
479 Add(Dividend);
480 }
481
482 /**
483 * Calculates square root of this integer.
484 */
485 void Sqrt()
486 {
487 BigInt Number(*this);
489
490 BigInt Bit(1);
492 while (Bit > Number)
493 {
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;
506 Result += Bit;
507 }
508 else
509 {
511 }
513 }
514 *this = Result;
515 }
516
517 /**
518 * Assignment operator for int64 values.
519 */
520 TBigInt& operator=(int64 Other)
521 {
522 Set(Other);
523 return *this;
524 }
525
526 /**
527 * Returns the index of the highest non-zero bit. -1 if no such bit exists.
528 */
530 {
531 for (int32 WordIndex = NumWords - 1; WordIndex >= 0; --WordIndex)
532 {
533 if (!!Bits[WordIndex])
534 {
536 for (BitIndex = BitsPerWord - 1; BitIndex >= 0 && !(Bits[WordIndex] & (1 << BitIndex)); --BitIndex);
537 return BitIndex + WordIndex * BitsPerWord;
538 }
539 }
540 return -1;
541 }
542
543 /**
544 * Returns a bit value as an integer value (0 or 1).
545 */
546 int32 GetBit(int32 BitIndex) const
547 {
550 return (Bits[WordIndex] & (1 << BitIndex)) ? 1 : 0;
551 }
552
553 /**
554 * Sets a bit value.
555 */
556 void SetBit(int32 BitIndex, int32 Value)
557 {
560 if (!!Value)
561 {
562 Bits[WordIndex] |= (1 << BitIndex);
563 }
564 else
565 {
566 Bits[WordIndex] &= ~(1 << BitIndex);
567 }
568 }
569
570 /**
571 * Shift left by the specified amount of bits.
572 *
573 * @param BitCount the number of bits to shift.
574 */
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 {
585 return;
586 }
587 else if (BitCount >= NumBits)
588 {
589 Zero();
590 return;
591 }
593 }
594
595 /**
596 * Shift right by the specified amount of bits.
597 *
598 * @param BitCount the number of bits to shift.
599 */
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 {
610 return;
611 }
612 else if (BitCount >= NumBits)
613 {
614 Zero();
615 return;
616 }
618 }
619
620 /**
621 * Bitwise 'or'
622 */
623 void BitwiseOr(const BigInt& Other)
624 {
626 {
628 }
629 }
630
631 /**
632 * Bitwise 'and'
633 */
634 void BitwiseAnd(const BigInt& Other)
635 {
637 {
639 }
640 }
641
642 /**
643 * Bitwise 'not'
644 */
646 {
648 {
650 }
651 }
652
653 /**
654 * Checks if two integers are equal.
655 */
656 bool IsEqual(const BigInt& Other) const
657 {
659 {
661 {
662 return false;
663 }
664 }
665
666 return true;
667 }
668
669 /**
670 * this < Other
671 */
672 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 }
687 return WordIndex >= 0 && Bits[WordIndex] < Other.Bits[WordIndex];
688 }
689
690 /**
691 * this <= Other
692 */
693 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 }
708 return WordIndex < 0 || Bits[WordIndex] < Other.Bits[WordIndex];
709 }
710
711 /**
712 * this > Other
713 */
714 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 }
729 return WordIndex >= 0 && Bits[WordIndex] > Other.Bits[WordIndex];
730 }
731
732 /**
733 * this >= Other
734 */
735 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 }
750 return WordIndex < 0 || Bits[WordIndex] > Other.Bits[WordIndex];
751 }
752
753 /**
754 * this == 0
755 */
756 bool IsZero() const
757 {
759 for (WordIndex = NumWords - 1; WordIndex >= 0 && !Bits[WordIndex]; --WordIndex);
760 return WordIndex < 0;
761 }
762
763 /**
764 * this > 0
765 */
766 bool IsGreaterThanZero() const
767 {
768 return !IsNegative() && !IsZero();
769 }
770
771 /**
772 * this < 0
773 */
774 bool IsLessThanZero() const
775 {
776 return IsNegative() && !IsZero();
777 }
778
779 bool IsFirstBitSet() const
780 {
781 return !!(Bits[0] & 1);
782 }
783 /**
784 * Bit indexing operator
785 */
786 bool operator[](int32 BitIndex) const
787 {
788 return GetBit(BitIndex);
789 }
790
791 // Begin operator overloads
792 BigInt operator>>(int32 Count) const
793 {
794 BigInt Result = *this;
796 return Result;
797 }
798
799 BigInt& operator>>=(int32 Count)
800 {
802 return *this;
803 }
804
805 BigInt operator<<(int32 Count) const
806 {
807 BigInt Result = *this;
809 return Result;
810 }
811
812 BigInt& operator<<=(int32 Count)
813 {
815 return *this;
816 }
817
818 BigInt operator+(const BigInt& Other) const
819 {
820 BigInt Result(*this);
822 return Result;
823 }
824
826 {
827 Add(One);
828 return *this;
829 }
830
831 BigInt& operator+=(const BigInt& Other)
832 {
833 Add(Other);
834 return *this;
835 }
836
837 BigInt operator-(const BigInt& Other) const
838 {
839 BigInt Result(*this);
841 return Result;
842 }
843
845 {
846 Subtract(One);
847 return *this;
848 }
849
850 BigInt& operator-=(const BigInt& Other)
851 {
853 return *this;
854 }
855
856 BigInt operator*(const BigInt& Other) const
857 {
858 BigInt Result(*this);
860 return Result;
861 }
862
863 BigInt& operator*=(const BigInt& Other)
864 {
866 return *this;
867 }
868
869 BigInt operator/(const BigInt& Divider) const
870 {
871 BigInt Result(*this);
873 return Result;
874 }
875
876 BigInt& operator/=(const BigInt& Divider)
877 {
879 return *this;
880 }
881
882 BigInt operator%(const BigInt& Modulus) const
883 {
884 BigInt Result(*this);
886 return Result;
887 }
888
889 BigInt& operator%=(const BigInt& Modulus)
890 {
892 return *this;
893 }
894
895 bool operator<(const BigInt& Other) const
896 {
897 return IsLess(Other);
898 }
899
900 bool operator<=(const BigInt& Other) const
901 {
902 return IsLessOrEqual(Other);
903 }
904
905 bool operator>(const BigInt& Other) const
906 {
907 return IsGreater(Other);
908 }
909
910 bool operator>=(const BigInt& Other) const
911 {
912 return IsGreaterOrEqual(Other);
913 }
914
915 bool operator==(const BigInt& Other) const
916 {
917 return IsEqual(Other);
918 }
919
920 bool operator!=(const BigInt& Other) const
921 {
922 return !IsEqual(Other);
923 }
924
925 BigInt operator&(const BigInt& Other) const
926 {
927 BigInt Result(*this);
929 return Result;
930 }
931
932 BigInt& operator&=(const BigInt& Other)
933 {
935 return *this;
936 }
937
938 BigInt operator|(const BigInt& Other) const
939 {
940 BigInt Result(*this);
942 return Result;
943 }
944
945 BigInt& operator|=(const BigInt& Other)
946 {
948 return *this;
949 }
950
952 {
953 BigInt Result(*this);
955 return Result;
956 }
957 // End operator overloads
958
959 /**
960 * Returns the value of this big int as a 64-bit integer. If the value is greater, the higher bits are truncated.
961 */
962 int64 ToInt() const
963 {
964 return (int64)Bits[0] + ((int64)Bits[1] << BitsPerWord);
965 }
966
967 /**
968 * Returns this big int as a string.
969 */
971 {
972 FString Text(TEXT("0x"));
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
988 /**
989 * Parses a string representing a hex value
990 */
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;
1002 {
1003 const TCHAR ByteChar = Value[CharIndex];
1004 const int32 ByteIndex = (Value.Len() - CharIndex - 1);
1006 const int32 ByteValue = ByteChar > '9' ? (FChar::ToUpper(ByteChar) - 'A' + 10) : (ByteChar - '0');
1007 check(ByteValue >= 0 && ByteValue <= 15);
1009 }
1010 }
1011
1012 /**
1013 * Serialization.
1014 */
1015 friend FArchive& operator<<(FArchive& Ar, BigInt& Value)
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>
1026TBigInt<NumBits, bSigned> TBigInt<NumBits, bSigned>::One(1LL);
1027
1028// Predefined big int types
1029typedef TBigInt<256> int256;
1030typedef TBigInt<512> int512;
1032
1033/**
1034 * Encryption key - exponent and modulus pair
1035 */
1036template <typename IntType>
1038{
1039 IntType Exponent;
1040 IntType Modulus;
1041};
1043
1044/**
1045 * Math utils for encryption.
1046 */
1048{
1049 /**
1050 * Greatest common divisor of ValueA and ValueB.
1051 */
1052 template <typename IntType>
1053 static 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
1099 /**
1100 * Multiplicative inverse of exponent using extended GCD algorithm.
1101 *
1102 * Extended gcd: ax + by = gcd(a, b), where a = exponent, b = fi(n), gcd(a, b) = gcd(e, fi(n)) = 1, fi(n) is the Euler's totient function of n
1103 * We only care to find d = x, which is our multiplicatve inverse of e (a).
1104 */
1105 template <typename IntType>
1106 static IntType CalculateMultiplicativeInverseOfExponent(IntType Exponent, IntType Totient)
1107 {
1108 IntType x0 = 1;
1109 IntType y0 = 0;
1110 IntType x1 = 0;
1111 IntType y1 = 1;
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
1142 /**
1143 * Generate Key Pair for encryption and decryption.
1144 */
1145 template <typename IntType>
1146 static 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
1153 do
1154 {
1157 }
1158 while (DecodeExponent == EncodeExponent);
1159
1162
1165 }
1166
1167 /**
1168 * Raise Base to power of Exponent in mod Modulus.
1169 */
1170 template <typename IntType>
1171 static 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
1187 /**
1188 * Encrypts a stream of bytes
1189 */
1190 template <typename IntType>
1191 static void EncryptBytes(IntType* EncryptedData, const uint8* Data, const int64 DataLength, const FEncryptionKey& EncryptionKey)
1192 {
1193 for (int Index = 0; Index < DataLength; ++Index)
1194 {
1196 }
1197 }
1198
1199 /**
1200 * Decrypts a stream of bytes
1201 */
1202 template <typename IntType>
1203 static void DecryptBytes(uint8* DecryptedData, const IntType* Data, const int64 DataLength, const FEncryptionKey& DecryptionKey)
1204 {
1205 for (int64 Index = 0; Index < DataLength; ++Index)
1206 {
1209 }
1210 }
1211}
1212
1213/// @cond DOXYGEN_WARNINGS
1214
1215/**
1216 * Specialization for int type used in encryption (performance). Avoids using temporary results and most of the operations are inplace.
1217 */
1218template <>
1219TEncryptionInt FEncryption::ModularPow(TEncryptionInt Base, TEncryptionInt Exponent, TEncryptionInt Modulus)
1220{
1221 TEncryptionInt Result(1LL);
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
1236/// @endcond
1237
1238template <class InDataType>
1240{
1241 typedef InDataType DataType;
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
1265 bool operator != (const FSignatureBase& InOther)
1266 {
1267 return Data != InOther.Data;
1268 }
1269
1270 bool operator == (const FSignatureBase& InOther)
1271 {
1272 return Data == InOther.Data;
1273 }
1274
1275 /**
1276 * Serialization.
1277 */
1278 friend FArchive& operator<<(FArchive& Ar, FSignatureBase& Value)
1279 {
1281 return Ar;
1282 }
1283};
1284
1286{
1287
1288};
1289
1291{
1292
1293};
1294
1295namespace FEncryption
1296{
1297 static void EncryptSignature(const FDecryptedSignature& InUnencryptedSignature, FEncryptedSignature& OutEncryptedSignature, const FEncryptionKey& EncryptionKey)
1298 {
1299 OutEncryptedSignature.Data = FEncryption::ModularPow(TEncryptionInt(InUnencryptedSignature.Data), EncryptionKey.Exponent, EncryptionKey.Modulus);
1300 }
1301
1302 static void DecryptSignature(const FEncryptedSignature& InEncryptedSignature, FDecryptedSignature& OutUnencryptedSignature, const FEncryptionKey& EncryptionKey)
1303 {
1304 OutUnencryptedSignature.Data = (FDecryptedSignature::DataType)FEncryption::ModularPow(TEncryptionInt(InEncryptedSignature.Data), EncryptionKey.Exponent, EncryptionKey.Modulus).ToInt();
1305 }
1306}
#define checkSlow(expr)
#define check(expr)
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:1108
#define FORCEINLINE
Definition Platform.h:644
#define UE_ARRAY_COUNT(array)
FORCEINLINE uint32 * GetBits()
Definition BigInt.h:82
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
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
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
static FORCEINLINE void RestoreSign(BigInt &Result, int32 SignA, int32 SignB)
Definition BigInt.h:72
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
FORCEINLINE 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
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
void ShiftLeftInternal(const int32 BitCount)
Definition BigInt.h:162
int32 Sign() const
Definition BigInt.h:300
FORCEINLINE void Zero()
Definition BigInt.h:93
void BitwiseNot()
Definition BigInt.h:645
static FORCEINLINE void MakePositiveFactors(BigInt &FactorA, int32 &SignA, BigInt &FactorB, int32 &SignB)
Definition BigInt.h:48
uint32 Bits[NumWords]
Definition BigInt.h:38
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
FORCEINLINE const uint32 * GetBits() const
Definition BigInt.h:87
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
BigInt & operator++()
Definition BigInt.h:825
BigInt & operator%=(const BigInt &Modulus)
Definition BigInt.h:889
@ NumWords
Definition BigInt.h:32
@ BitsPerWord
Definition BigInt.h:31
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
static IntType CalculateMultiplicativeInverseOfExponent(IntType Exponent, IntType Totient)
Definition BigInt.h:1106
static void EncryptBytes(IntType *EncryptedData, const uint8 *Data, const int64 DataLength, const FEncryptionKey &EncryptionKey)
Definition BigInt.h:1191
static void EncryptSignature(const FDecryptedSignature &InUnencryptedSignature, FEncryptedSignature &OutEncryptedSignature, const FEncryptionKey &EncryptionKey)
Definition BigInt.h:1297
static IntType CalculateGCD(IntType ValueA, IntType ValueB)
Definition BigInt.h:1053
static void DecryptSignature(const FEncryptedSignature &InEncryptedSignature, FDecryptedSignature &OutUnencryptedSignature, const FEncryptionKey &EncryptionKey)
Definition BigInt.h:1302
static IntType ModularPow(IntType Base, IntType Exponent, IntType Modulus)
Definition BigInt.h:1171
static void DecryptBytes(uint8 *DecryptedData, const IntType *Data, const int64 DataLength, const FEncryptionKey &DecryptionKey)
Definition BigInt.h:1203
static void GenerateKeyPair(const IntType &P, const IntType &Q, FEncryptionKey &PublicKey, FEncryptionKey &PrivateKey)
Definition BigInt.h:1146
bool operator==(const FSignatureBase &InOther)
Definition BigInt.h:1270
bool operator!=(const FSignatureBase &InOther)
Definition BigInt.h:1265
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
IntType Modulus
Definition BigInt.h:1040
IntType Exponent
Definition BigInt.h:1039