Botan  1.11.15
src/lib/math/bigint/big_code.cpp
Go to the documentation of this file.
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 }