84 lines
2.6 KiB
C#
Raw Normal View History

2014-01-06 09:27:48 +01:00
using System;
using System.Linq;
using System.Numerics;
namespace S22.Sasl.Mechanisms.Srp {
/// <summary>
/// Represents a "multi-precision integer" (MPI) as is described in the
/// SRP specification (3.2 Multi-Precision Integers, p.5).
/// </summary>
/// <remarks>Multi-Precision Integers, or MPIs, are positive integers used
/// to hold large integers used in cryptographic computations.</remarks>
internal class Mpi {
/// <summary>
/// The underlying BigInteger instance used to represent this
/// "multi-precision integer".
/// </summary>
public BigInteger Value {
get;
set;
}
/// <summary>
/// Creates a new "multi-precision integer" from the specified array
/// of bytes.
/// </summary>
/// <param name="data">A big-endian sequence of bytes forming the
/// integer value of the multi-precision integer.</param>
public Mpi(byte[] data) {
byte[] b = new byte[data.Length];
Array.Copy(data.Reverse().ToArray(), b, data.Length);
ByteBuilder builder = new ByteBuilder().Append(b);
// We append a null byte to the buffer which ensures the most
// significant bit will never be set and the big integer value
// always be positive.
if (b.Last() != 0)
builder.Append(0);
Value = new BigInteger(builder.ToArray());
}
/// <summary>
/// Creates a new "multi-precision integer" from the specified BigInteger
/// instance.
/// </summary>
/// <param name="value">The BigInteger instance to initialize the MPI
/// with.</param>
public Mpi(BigInteger value)
: this(value.ToByteArray().Reverse().ToArray()) {
}
/// <summary>
/// Returns a sequence of bytes in big-endian order forming the integer
/// value of this "multi-precision integer" instance.
/// </summary>
/// <returns>Returns a sequence of bytes in big-endian order representing
/// this "multi-precision integer" instance.</returns>
public byte[] ToBytes() {
byte[] b = Value.ToByteArray().Reverse().ToArray();
// Strip off the 0 byte.
if (b[0] == 0)
return b.Skip(1).ToArray();
return b;
}
/// <summary>
/// Serializes the "multi-precision integer" into a sequence of bytes
/// according to the requirements of the SRP specification.
/// </summary>
/// <returns>A big-endian sequence of bytes representing the integer
/// value of the MPI.</returns>
public byte[] Serialize() {
// MPI's expect a big-endian sequence of bytes forming the integer
// value, whereas BigInteger uses little-endian.
byte[] data = ToBytes();
ushort length = Convert.ToUInt16(data.Length);
return new ByteBuilder()
.Append(length, true)
.Append(data)
.ToArray();
}
}
}