00001
00002
00003
00004
00005
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
00017
00018 void BigInt::encode(byte output[], const BigInt& n, Base base)
00019 {
00020 if(base == Binary)
00021 n.binary_encode(output);
00022 else if(base == Hexadecimal)
00023 {
00024 SecureVector<byte> binary(n.encoded_size(Binary));
00025 n.binary_encode(binary);
00026 for(u32bit j = 0; j != binary.size(); ++j)
00027 Hex_Encoder::encode(binary[j], output + 2*j);
00028 }
00029 else if(base == Octal)
00030 {
00031 BigInt copy = n;
00032 const u32bit output_size = n.encoded_size(Octal);
00033 for(u32bit j = 0; j != output_size; ++j)
00034 {
00035 output[output_size - 1 - j] = Charset::digit2char(copy % 8);
00036 copy /= 8;
00037 }
00038 }
00039 else if(base == Decimal)
00040 {
00041 BigInt copy = n;
00042 BigInt remainder;
00043 copy.set_sign(Positive);
00044 const u32bit output_size = n.encoded_size(Decimal);
00045 for(u32bit j = 0; j != output_size; ++j)
00046 {
00047 divide(copy, 10, copy, remainder);
00048 output[output_size - 1 - j] =
00049 Charset::digit2char(remainder.word_at(0));
00050 if(copy.is_zero())
00051 break;
00052 }
00053 }
00054 else
00055 throw Invalid_Argument("Unknown BigInt encoding method");
00056 }
00057
00058
00059
00060
00061 SecureVector<byte> BigInt::encode(const BigInt& n, Base base)
00062 {
00063 SecureVector<byte> output(n.encoded_size(base));
00064 encode(output, n, base);
00065 if(base != Binary)
00066 for(u32bit j = 0; j != output.size(); ++j)
00067 if(output[j] == 0)
00068 output[j] = '0';
00069 return output;
00070 }
00071
00072
00073
00074
00075 SecureVector<byte> BigInt::encode_1363(const BigInt& n, u32bit bytes)
00076 {
00077 const u32bit n_bytes = n.bytes();
00078 if(n_bytes > bytes)
00079 throw Encoding_Error("encode_1363: n is too large to encode properly");
00080
00081 const u32bit leading_0s = bytes - n_bytes;
00082
00083 SecureVector<byte> output(bytes);
00084 encode(output + leading_0s, n, Binary);
00085 return output;
00086 }
00087
00088
00089
00090
00091 BigInt BigInt::decode(const MemoryRegion<byte>& buf, Base base)
00092 {
00093 return BigInt::decode(buf, buf.size(), base);
00094 }
00095
00096
00097
00098
00099 BigInt BigInt::decode(const byte buf[], u32bit length, Base base)
00100 {
00101 BigInt r;
00102 if(base == Binary)
00103 r.binary_decode(buf, length);
00104 else if(base == Hexadecimal)
00105 {
00106 SecureVector<byte> hex;
00107 for(u32bit j = 0; j != length; ++j)
00108 if(Hex_Decoder::is_valid(buf[j]))
00109 hex.append(buf[j]);
00110
00111 u32bit offset = (hex.size() % 2);
00112 SecureVector<byte> binary(hex.size() / 2 + offset);
00113
00114 if(offset)
00115 {
00116 byte temp[2] = { '0', hex[0] };
00117 binary[0] = Hex_Decoder::decode(temp);
00118 }
00119
00120 for(u32bit j = offset; j != binary.size(); ++j)
00121 binary[j] = Hex_Decoder::decode(hex+2*j-offset);
00122 r.binary_decode(binary, binary.size());
00123 }
00124 else if(base == Decimal || base == Octal)
00125 {
00126 const u32bit RADIX = ((base == Decimal) ? 10 : 8);
00127 for(u32bit j = 0; j != length; ++j)
00128 {
00129 if(Charset::is_space(buf[j]))
00130 continue;
00131
00132 if(!Charset::is_digit(buf[j]))
00133 throw Invalid_Argument("BigInt::decode: "
00134 "Invalid character in decimal input");
00135
00136 byte x = Charset::char2digit(buf[j]);
00137 if(x >= RADIX)
00138 {
00139 if(RADIX == 10)
00140 throw Invalid_Argument("BigInt: Invalid decimal string");
00141 else
00142 throw Invalid_Argument("BigInt: Invalid octal string");
00143 }
00144
00145 r *= RADIX;
00146 r += x;
00147 }
00148 }
00149 else
00150 throw Invalid_Argument("Unknown BigInt decoding method");
00151 return r;
00152 }
00153
00154 }