1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/*************************************************
* BigInt Encoding/Decoding Source File *
* (C) 1999-2005 The Botan Project *
*************************************************/
#include <botan/bigint.h>
#include <botan/numthry.h>
#include <botan/charset.h>
#include <botan/hex.h>
namespace Botan {
/*************************************************
* Encode a BigInt *
*************************************************/
void BigInt::encode(byte output[], const BigInt& n, Base base)
{
if(base == Binary)
n.binary_encode(output);
else if(base == Hexadecimal)
{
SecureVector<byte> binary(n.encoded_size(Binary));
n.binary_encode(binary);
for(u32bit j = 0; j != binary.size(); j++)
Hex_Encoder::encode(binary[j], output + 2*j);
}
else if(base == Octal)
{
BigInt copy = n;
const u32bit output_size = n.encoded_size(Octal);
for(u32bit j = 0; j != output_size; j++)
{
output[output_size - 1 - j] = digit2char(copy % 8);
copy /= 8;
}
}
else if(base == Decimal)
{
BigInt copy = n;
BigInt remainder;
copy.set_sign(Positive);
const u32bit output_size = n.encoded_size(Decimal);
for(u32bit j = 0; j != output_size; j++)
{
divide(copy, 10, copy, remainder);
output[output_size - 1 - j] = digit2char(remainder.word_at(0));
if(copy.is_zero())
break;
}
}
else
throw Invalid_Argument("Unknown BigInt encoding method");
}
/*************************************************
* Encode a BigInt *
*************************************************/
SecureVector<byte> BigInt::encode(const BigInt& n, Base base)
{
SecureVector<byte> output(n.encoded_size(base));
encode(output, n, base);
if(base != Binary)
for(u32bit j = 0; j != output.size(); j++)
if(output[j] == 0)
output[j] = '0';
return output;
}
/*************************************************
* Encode a BigInt, with leading 0s if needed *
*************************************************/
SecureVector<byte> BigInt::encode_1363(const BigInt& n, u32bit bytes)
{
const u32bit n_bytes = n.bytes();
if(n_bytes > bytes)
throw Encoding_Error("encode_1363: n is too large to encode properly");
const u32bit leading_0s = bytes - n_bytes;
SecureVector<byte> output(bytes);
encode(output + leading_0s, n, Binary);
return output;
}
/*************************************************
* Decode a BigInt *
*************************************************/
BigInt BigInt::decode(const MemoryRegion<byte>& buf, Base base)
{
return BigInt::decode(buf, buf.size(), base);
}
/*************************************************
* Decode a BigInt *
*************************************************/
BigInt BigInt::decode(const byte buf[], u32bit length, Base base)
{
BigInt r;
if(base == Binary)
r.binary_decode(buf, length);
else if(base == Hexadecimal)
{
SecureVector<byte> hex;
for(u32bit j = 0; j != length; j++)
if(Hex_Decoder::is_valid(buf[j]))
hex.append(buf[j]);
u32bit offset = (hex.size() % 2);
SecureVector<byte> binary(hex.size() / 2 + offset);
if(offset)
{
byte temp[2] = { '0', hex[0] };
binary[0] = Hex_Decoder::decode(temp);
}
for(u32bit j = offset; j != binary.size(); j++)
binary[j] = Hex_Decoder::decode(hex+2*j-offset);
r.binary_decode(binary, binary.size());
}
else if(base == Decimal || base == Octal)
{
const u32bit RADIX = ((base == Decimal) ? 10 : 8);
for(u32bit j = 0; j != length; j++)
{
byte x = char2digit(buf[j]);
if(x >= RADIX)
{
if(RADIX == 10)
throw Invalid_Argument("BigInt: Invalid decimal string");
else
throw Invalid_Argument("BigInt: Invalid octal string");
}
r = RADIX * r + x;
}
}
else
throw Invalid_Argument("Unknown BigInt decoding method");
return r;
}
}
|