Botan
1.11.15
|
00001 /* 00002 * BigInt Encoding/Decoding 00003 * (C) 1999-2010,2012 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/bigint.h> 00009 #include <botan/divide.h> 00010 #include <botan/charset.h> 00011 #include <botan/hex.h> 00012 00013 namespace Botan { 00014 00015 /* 00016 * Encode a BigInt 00017 */ 00018 void BigInt::encode(byte output[], const BigInt& n, Base base) 00019 { 00020 if(base == Binary) 00021 { 00022 n.binary_encode(output); 00023 } 00024 else if(base == Hexadecimal) 00025 { 00026 secure_vector<byte> binary(n.encoded_size(Binary)); 00027 n.binary_encode(&binary[0]); 00028 00029 hex_encode(reinterpret_cast<char*>(output), 00030 &binary[0], binary.size()); 00031 } 00032 else if(base == Decimal) 00033 { 00034 BigInt copy = n; 00035 BigInt remainder; 00036 copy.set_sign(Positive); 00037 const size_t output_size = n.encoded_size(Decimal); 00038 for(size_t j = 0; j != output_size; ++j) 00039 { 00040 divide(copy, 10, copy, remainder); 00041 output[output_size - 1 - j] = 00042 Charset::digit2char(static_cast<byte>(remainder.word_at(0))); 00043 if(copy.is_zero()) 00044 break; 00045 } 00046 } 00047 else 00048 throw Invalid_Argument("Unknown BigInt encoding method"); 00049 } 00050 00051 /* 00052 * Encode a BigInt 00053 */ 00054 std::vector<byte> BigInt::encode(const BigInt& n, Base base) 00055 { 00056 std::vector<byte> output(n.encoded_size(base)); 00057 encode(&output[0], n, base); 00058 if(base != Binary) 00059 for(size_t j = 0; j != output.size(); ++j) 00060 if(output[j] == 0) 00061 output[j] = '0'; 00062 return output; 00063 } 00064 00065 /* 00066 * Encode a BigInt 00067 */ 00068 secure_vector<byte> BigInt::encode_locked(const BigInt& n, Base base) 00069 { 00070 secure_vector<byte> output(n.encoded_size(base)); 00071 encode(&output[0], n, base); 00072 if(base != Binary) 00073 for(size_t j = 0; j != output.size(); ++j) 00074 if(output[j] == 0) 00075 output[j] = '0'; 00076 return output; 00077 } 00078 00079 /* 00080 * Encode a BigInt, with leading 0s if needed 00081 */ 00082 secure_vector<byte> BigInt::encode_1363(const BigInt& n, size_t bytes) 00083 { 00084 const size_t n_bytes = n.bytes(); 00085 if(n_bytes > bytes) 00086 throw Encoding_Error("encode_1363: n is too large to encode properly"); 00087 00088 const size_t leading_0s = bytes - n_bytes; 00089 00090 secure_vector<byte> output(bytes); 00091 encode(&output[leading_0s], n, Binary); 00092 return output; 00093 } 00094 00095 /* 00096 * Decode a BigInt 00097 */ 00098 BigInt BigInt::decode(const byte buf[], size_t length, Base base) 00099 { 00100 BigInt r; 00101 if(base == Binary) 00102 r.binary_decode(buf, length); 00103 else if(base == Hexadecimal) 00104 { 00105 secure_vector<byte> binary; 00106 00107 if(length % 2) 00108 { 00109 // Handle lack of leading 0 00110 const char buf0_with_leading_0[2] = 00111 { '0', static_cast<char>(buf[0]) }; 00112 00113 binary = hex_decode_locked(buf0_with_leading_0, 2); 00114 00115 binary += hex_decode_locked(reinterpret_cast<const char*>(&buf[1]), 00116 length - 1, 00117 false); 00118 } 00119 else 00120 binary = hex_decode_locked(reinterpret_cast<const char*>(buf), 00121 length, false); 00122 00123 r.binary_decode(&binary[0], binary.size()); 00124 } 00125 else if(base == Decimal) 00126 { 00127 for(size_t i = 0; i != length; ++i) 00128 { 00129 if(Charset::is_space(buf[i])) 00130 continue; 00131 00132 if(!Charset::is_digit(buf[i])) 00133 throw Invalid_Argument("BigInt::decode: " 00134 "Invalid character in decimal input"); 00135 00136 const byte x = Charset::char2digit(buf[i]); 00137 00138 if(x >= 10) 00139 throw Invalid_Argument("BigInt: Invalid decimal string"); 00140 00141 r *= 10; 00142 r += x; 00143 } 00144 } 00145 else 00146 throw Invalid_Argument("Unknown BigInt decoding method"); 00147 return r; 00148 } 00149 00150 }