Пример #1
0
        public void KeysAreRandomBase32(string encodedKey)
        {
            var base32AlphabetBytes = Base32Alphabet.ToBytesFromAscii();
            var numberOfKeys        = Faker.Random.Int(10, 200);

            var keysWithPossibleDuplicates = new List <string>();
            var keysWithNoDuplicates       = new HashSet <string>();

            $"When I create many ({numberOfKeys}) keys"
            .x(() =>
            {
                for (var i = 0; i < numberOfKeys; i++)
                {
                    encodedKey = TestInstance.CreateKey();
                    keysWithPossibleDuplicates.Add(encodedKey);
                    keysWithNoDuplicates.Add(encodedKey);
                }
            });

            "Then encoded keys are random and unique"
            .x(() => keysWithPossibleDuplicates.Count.ShouldBe(keysWithNoDuplicates.Count));

            "And the encoded keys are Base32"
            .x(() => keysWithNoDuplicates.First().ToBytesFromAscii().ShouldAllBe(x => base32AlphabetBytes.Contains(x)));

            /*
             * There is no easy way to test for sufficient randomness as specified in
             * RFC 4086 https://tools.ietf.org/html/rfc4086.
             *
             * Trust the output from System.Security.Cryptography.RandomNumberGenerator
             */
        }
Пример #2
0
        public void ctorWithPaddingChar_Works()
        {
            // alphabet characters are unimportant here
            var alpha = new Base32Alphabet("0123456789abcdef0123456789abcdef", '!');

            Assert.AreEqual('!', alpha.PaddingChar);
        }
Пример #3
0
        public byte[] Decrypt(string input)
        {
            byte newChar = 0x0;
            //填充新字所缺位元數
            int leaNewCharBitCounter = FixedByteCounter;
            //拿來使用的位元組所剩的位元數
            int reminderBitCounter = 0;
            //用剩下的位元組
            byte reminderByte = 0x0;

            List <byte> result = new List <byte>();

            //去掉padding
            input = input.Replace("=", "");
            byte[] byteResult = new byte[input.Length];
            //把base32alphabet結果轉換成byte array
            for (int k = 0; k < input.Length; k++)
            {
                byteResult[k] = Convert.ToByte(Base32Alphabet.IndexOf(input[k]));
            }

            for (int i = 0; i < byteResult.Length; i++)
            {
                //空出newChar所需的空間
                newChar |= (reminderByte <<= (FixedByteCounter - reminderBitCounter));
                //埴充newChar所缺的bit數
                leaNewCharBitCounter -= reminderBitCounter;

                if (leaNewCharBitCounter > FixedDrawCounter)
                {
                    newChar |= (byte)(byteResult[i] << (leaNewCharBitCounter - FixedDrawCounter));
                    leaNewCharBitCounter -= FixedDrawCounter;
                    reminderBitCounter    = 0;
                }
                else if (leaNewCharBitCounter == FixedDrawCounter)
                {
                    newChar |= byteResult[i];
                    leaNewCharBitCounter = 0;
                    reminderBitCounter   = 0;
                }
                else if (leaNewCharBitCounter < FixedDrawCounter)
                {
                    newChar             |= (byte)(byteResult[i] >> (FixedDrawCounter - leaNewCharBitCounter));
                    reminderBitCounter   = FixedDrawCounter - leaNewCharBitCounter;
                    reminderByte         = byteResult[i] &= Convert.ToByte(Math.Pow(2, reminderBitCounter) - 1);
                    leaNewCharBitCounter = 0;
                }

                if (leaNewCharBitCounter == 0)
                {
                    result.Add(newChar);
                    newChar = 0x0;
                    leaNewCharBitCounter = FixedByteCounter;
                }
            }

            return(result.ToArray());
        }
Пример #4
0
    /// <summary>
    /// Convert <paramref name="base32String"/> string to a byte array
    /// </summary>
    /// <param name="base32String">Base32 string to convert - must be at least two characters</param>
    public static Maybe <byte[]> FromBase32String(string base32String)
    {
        // Check if string is empty
        if (string.IsNullOrEmpty(base32String))
        {
            return(Array.Empty <byte>());
        }

        // Convert to upper-case
        var base32StringUpperCase = base32String.ToUpperInvariant();

        // Prepare output byte array
        var outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize];

        // Check the size
        if (outputBytes.Length == 0)
        {
            return(F.None <byte[], M.InputStringNotLongEnoughMsg>());
        }

        // Position in the string
        var base32Position = 0;

        // Offset inside the character in the string
        var base32SubPosition = 0;

        // Position within outputBytes array
        var outputBytePosition = 0;

        // The number of bits filled in the current output byte
        var outputByteSubPosition = 0;

        // Normally we would iterate on the input array but in this case we actually iterate on the output array
        // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time
        while (outputBytePosition < outputBytes.Length)
        {
            // Look up current character in the dictionary to convert it to byte
            var currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]);

            // Check if found
            if (currentBase32Byte < 0)
            {
                return(F.None <byte[]>(new M.CharacterNotInBase32AlphabetMsg(base32String[base32Position])));
            }

            // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte
            var bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition);

            // Make space in the output byte
            outputBytes[outputBytePosition] <<= bitsAvailableInByte;

            // Extract the part of the input character and move it to the output byte
            outputBytes[outputBytePosition] |= (byte)(currentBase32Byte >> (OutByteSize - (base32SubPosition + bitsAvailableInByte)));

            // Update current sub-byte position
            outputByteSubPosition += bitsAvailableInByte;

            // Check overflow
            if (outputByteSubPosition >= InByteSize)
            {
                // Move to the next byte
                outputBytePosition++;
                outputByteSubPosition = 0;
            }

            // Update current base32 byte completion
            base32SubPosition += bitsAvailableInByte;

            // Check overflow or end of input array
            if (base32SubPosition >= OutByteSize)
            {
                // Move to the next character
                base32Position++;
                base32SubPosition = 0;
            }
        }

        return(outputBytes);
    }
Пример #5
0
        private byte[] FromBase32String(string base32String)
        {
            const int    InByteSize     = 8;
            const int    OutByteSize    = 5;
            const string Base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

            // Check if string is null
            if (base32String == null)
            {
                return(null);
            }
            // Check if empty
            else if (base32String == string.Empty)
            {
                return(new byte[0]);
            }

            // Convert to upper-case
            string base32StringUpperCase = base32String.ToUpperInvariant();

            // Prepare output byte array
            byte[] outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize];

            // Check the size
            if (outputBytes.Length == 0)
            {
                throw new ArgumentException("Specified string is not valid Base32 format because it doesn't have enough data to construct a complete byte array");
            }

            // Position in the string
            int base32Position = 0;

            // Offset inside the character in the string
            int base32SubPosition = 0;

            // Position within outputBytes array
            int outputBytePosition = 0;

            // The number of bits filled in the current output byte
            int outputByteSubPosition = 0;

            // Normally we would iterate on the input array but in this case we actually iterate on the output array
            // We do it because output array doesn't have overflow bits, while input does and it will cause output array overflow if we don't stop in time
            while (outputBytePosition < outputBytes.Length)
            {
                // Look up current character in the dictionary to convert it to byte
                int currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]);

                // Check if found
                if (currentBase32Byte < 0)
                {
                    throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position]));
                }

                // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte
                int bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition);

                // Make space in the output byte
                outputBytes[outputBytePosition] <<= bitsAvailableInByte;

                // Extract the part of the input character and move it to the output byte
                outputBytes[outputBytePosition] |= (byte)(currentBase32Byte >> (OutByteSize - (base32SubPosition + bitsAvailableInByte)));

                // Update current sub-byte position
                outputByteSubPosition += bitsAvailableInByte;

                // Check overflow
                if (outputByteSubPosition >= InByteSize)
                {
                    // Move to the next byte
                    outputBytePosition++;
                    outputByteSubPosition = 0;
                }

                // Update current base32 byte completion
                base32SubPosition += bitsAvailableInByte;

                // Check overflow or end of input array
                if (base32SubPosition >= OutByteSize)
                {
                    // Move to the next character
                    base32Position++;
                    base32SubPosition = 0;
                }
            }

            return(outputBytes);
        }
Пример #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Base32"/> class with a
 /// custom alphabet.
 /// </summary>
 /// <param name="alphabet">Alphabet to use.</param>
 public Base32(Base32Alphabet alphabet)
 {
     Alphabet = alphabet;
 }