| | | 1 | | using System; |
| | | 2 | | |
| | | 3 | | using Renci.SshNet.Security.Org.BouncyCastle.Math; |
| | | 4 | | using Renci.SshNet.Security.Org.BouncyCastle.Security; |
| | | 5 | | |
| | | 6 | | namespace Renci.SshNet.Security.Org.BouncyCastle.Utilities |
| | | 7 | | { |
| | | 8 | | /** |
| | | 9 | | * BigInteger utilities. |
| | | 10 | | */ |
| | | 11 | | internal abstract class BigIntegers |
| | | 12 | | { |
| | | 13 | | private const int MaxIterations = 1000; |
| | | 14 | | |
| | | 15 | | /** |
| | | 16 | | * Return the passed in value as an unsigned byte array. |
| | | 17 | | * |
| | | 18 | | * @param value value to be converted. |
| | | 19 | | * @return a byte array without a leading zero byte if present in the signed encoding. |
| | | 20 | | */ |
| | | 21 | | public static byte[] AsUnsignedByteArray( |
| | | 22 | | BigInteger n) |
| | 0 | 23 | | { |
| | 0 | 24 | | return n.ToByteArrayUnsigned(); |
| | 0 | 25 | | } |
| | | 26 | | |
| | | 27 | | /** |
| | | 28 | | * Return the passed in value as an unsigned byte array of specified length, zero-extended as necessary. |
| | | 29 | | * |
| | | 30 | | * @param length desired length of result array. |
| | | 31 | | * @param n value to be converted. |
| | | 32 | | * @return a byte array of specified length, with leading zeroes as necessary given the size of n. |
| | | 33 | | */ |
| | | 34 | | public static byte[] AsUnsignedByteArray(int length, BigInteger n) |
| | 36 | 35 | | { |
| | 36 | 36 | | byte[] bytes = n.ToByteArrayUnsigned(); |
| | | 37 | | |
| | 36 | 38 | | if (bytes.Length > length) |
| | 0 | 39 | | throw new ArgumentException("standard length exceeded", "n"); |
| | | 40 | | |
| | 36 | 41 | | if (bytes.Length == length) |
| | 28 | 42 | | return bytes; |
| | | 43 | | |
| | 8 | 44 | | byte[] tmp = new byte[length]; |
| | 8 | 45 | | Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length); |
| | 8 | 46 | | return tmp; |
| | 36 | 47 | | } |
| | | 48 | | |
| | | 49 | | /** |
| | | 50 | | * Return a random BigInteger not less than 'min' and not greater than 'max' |
| | | 51 | | * |
| | | 52 | | * @param min the least value that may be generated |
| | | 53 | | * @param max the greatest value that may be generated |
| | | 54 | | * @param random the source of randomness |
| | | 55 | | * @return a random BigInteger value in the range [min,max] |
| | | 56 | | */ |
| | | 57 | | public static BigInteger CreateRandomInRange( |
| | | 58 | | BigInteger min, |
| | | 59 | | BigInteger max, |
| | | 60 | | // TODO Should have been just Random class |
| | | 61 | | SecureRandom random) |
| | 0 | 62 | | { |
| | 0 | 63 | | int cmp = min.CompareTo(max); |
| | 0 | 64 | | if (cmp >= 0) |
| | 0 | 65 | | { |
| | 0 | 66 | | if (cmp > 0) |
| | 0 | 67 | | throw new ArgumentException("'min' may not be greater than 'max'"); |
| | | 68 | | |
| | 0 | 69 | | return min; |
| | | 70 | | } |
| | | 71 | | |
| | 0 | 72 | | if (min.BitLength > max.BitLength / 2) |
| | 0 | 73 | | { |
| | 0 | 74 | | return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min); |
| | | 75 | | } |
| | | 76 | | |
| | 0 | 77 | | for (int i = 0; i < MaxIterations; ++i) |
| | 0 | 78 | | { |
| | 0 | 79 | | BigInteger x = new BigInteger(max.BitLength, random); |
| | 0 | 80 | | if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0) |
| | 0 | 81 | | { |
| | 0 | 82 | | return x; |
| | | 83 | | } |
| | 0 | 84 | | } |
| | | 85 | | |
| | | 86 | | // fall back to a faster (restricted) method |
| | 0 | 87 | | return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min); |
| | 0 | 88 | | } |
| | | 89 | | |
| | | 90 | | public static int GetUnsignedByteLength(BigInteger n) |
| | 0 | 91 | | { |
| | 0 | 92 | | return (n.BitLength + 7) / 8; |
| | 0 | 93 | | } |
| | | 94 | | } |
| | | 95 | | } |