Esempio n. 1
0
        private byte[] CreateChecksum(byte[] data, int offset, int count, Bech32EncodingType encodingType)
#endif
        {
#if HAS_SPAN
            Span <byte> values = _HrpExpand.Length + data.Length + 6 is int v && v > 256 ? new byte[v] :
                                 stackalloc byte[v];
#else
            var values = new byte[_HrpExpand.Length + count + 6];
#endif
            var valuesOffset = 0;
#if HAS_SPAN
            _HrpExpand.AsSpan().CopyTo(values.Slice(valuesOffset));
#else
            Array.Copy(_HrpExpand, 0, values, valuesOffset, _HrpExpand.Length);
#endif
            valuesOffset += _HrpExpand.Length;
#if HAS_SPAN
            data.CopyTo(values.Slice(valuesOffset));
#else
            Array.Copy(data, offset, values, valuesOffset, count);
#endif
            valuesOffset += data.Length;
            var polymod = Polymod(values) ^ encodingType.EncodingConstant;
#if !HAS_SPAN
            var ret = new byte[6];
#endif
            foreach (var i in Enumerable.Range(0, 6))
            {
                ret[i] = (byte)((polymod >> 5 * (5 - i)) & 31);
            }
#if !HAS_SPAN
            return(ret);
#endif
        }
Esempio n. 2
0
        public virtual string EncodeData(ReadOnlySpan <byte> data, Bech32EncodingType encodingType)
#endif
        {
            if (encodingType == null)
            {
                throw new ArgumentNullException(nameof(encodingType));
            }
#if HAS_SPAN
            Span <byte> combined = _Hrp.Length + 1 + data.Length + 6 is int v && v > 256 ? new byte[v] :
                                   stackalloc byte[v];
#else
            var combined = new byte[_Hrp.Length + 1 + count + 6];
#endif
            int combinedOffset = 0;
#if HAS_SPAN
            _Hrp.CopyTo(combined);
#else
            Array.Copy(_Hrp, 0, combined, 0, _Hrp.Length);
#endif
            combinedOffset          += _Hrp.Length;
            combined[combinedOffset] = 49;
            combinedOffset++;
#if HAS_SPAN
            data.CopyTo(combined.Slice(combinedOffset));
#else
            Array.Copy(data, offset, combined, combinedOffset, count);
#endif
            combinedOffset += data.Length;
#if HAS_SPAN
            Span <byte> checkSum = stackalloc byte[6];
            CreateChecksum(data, encodingType, checkSum);
#else
            var checkSum = CreateChecksum(data, offset, count, encodingType);
#endif
#if HAS_SPAN
            checkSum.CopyTo(combined.Slice(combinedOffset, 6));
            combinedOffset += 6;
            for (int i = 0; i < data.Length + 6; i++)
#else
            Array.Copy(checkSum, 0, combined, combinedOffset, 6);
            combinedOffset += 6;
            for (int i = 0; i < count + 6; i++)
#endif
            {
                combined[_Hrp.Length + 1 + i] = Byteset[combined[_Hrp.Length + 1 + i]];
            }
            return(Encoders.ASCII.EncodeData(combined));
        }
Esempio n. 3
0
        protected virtual bool VerifyChecksum(byte[] data, int bechStringLen, out Bech32EncodingType encodingType, out int[] errorPosition)
#endif
        {
            errorPosition = null;
#if HAS_SPAN
            Span <byte> values = _HrpExpand.Length + data.Length is int v && v > 256 ? new byte[v] : stackalloc byte[v];
            _HrpExpand.CopyTo(values);
            data.CopyTo(values.Slice(_HrpExpand.Length));
#else
            var values = _HrpExpand.Concat(data);
#endif
            var polymod = Polymod(values);
            if (polymod == Bech32EncodingType.BECH32.EncodingConstant)
            {
                encodingType = Bech32EncodingType.BECH32;
            }
            else if (polymod == Bech32EncodingType.BECH32M.EncodingConstant)
            {
                encodingType = Bech32EncodingType.BECH32M;
            }
            else
            {
                encodingType = null;

                var epos = Bech32EncodingType.All
                           .Select(e => locate_errors(polymod ^ (uint)e.EncodingConstant, bechStringLen - 1))
                           .Where(e => e.Length != 0)
                           .OrderByDescending(e => e.Length)
                           .FirstOrDefault();
                errorPosition = epos;
                if (epos is null || epos.Length == 0)
                {
                    return(false);
                }
                for (var ep = 0; ep < epos.Length; ++ep)
                {
                    epos[ep] = bechStringLen - epos[ep] - (epos[ep] >= data.Length ? 2 : 1);
                }
                return(false);
            }
            return(true);
        }
Esempio n. 4
0
 public string EncodeRaw(byte[] data, Bech32EncodingType encodingType)
 {
     return(EncodeData(data, 0, data.Length, encodingType));
 }
Esempio n. 5
0
 public string EncodeRaw(ReadOnlySpan <byte> data, Bech32EncodingType encodingType)
 {
     return(EncodeData(data, encodingType));
 }
Esempio n. 6
0
 public string EncodeRaw(byte[] data, Bech32EncodingType encodingType)
 {
     return(EncodeData(data.AsSpan(), encodingType));
 }
Esempio n. 7
0
        protected virtual byte[] DecodeDataCore(string encoded, out Bech32EncodingType encodingType)
        {
            if (encoded == null)
            {
                throw new ArgumentNullException(nameof(encoded));
            }
            CheckCase(encoded);
            encoded = encoded.ToLowerInvariant();
#if HAS_SPAN
            Span <byte> buffer = encoded.Length is int v && v > 256 ? new byte[v] : stackalloc byte[v];
            ((ASCIIEncoder)Encoders.ASCII).DecodeData(encoded, buffer);
#else
            var buffer = Encoders.ASCII.DecodeData(encoded);
#endif
            var pos = encoded.LastIndexOf("1", StringComparison.OrdinalIgnoreCase);
            if (pos < 1)
            {
                throw new FormatException("The Bech32 string is missing separator '1'");
            }
            else if (pos + 7 > encoded.Length)
            {
                throw new FormatException("The Bech32 string is too short");
            }
            else if (StrictLength && encoded.Length > 90)
            {
                throw new FormatException("The Bech32 string is too long");
            }
            if (pos != _Hrp.Length)
            {
                throw new FormatException("Mismatching human readable part");
            }

            for (int i = 0; i < _Hrp.Length; i++)
            {
                if (buffer[i] != _Hrp[i])
                {
                    throw new FormatException("Mismatching human readable part");
                }
            }
#if HAS_SPAN
            Span <byte> data = encoded.Length - pos - 1 is int v2 && v2 > 256 ? new byte[v2] : stackalloc byte[v2];
#else
            var data = new byte[encoded.Length - pos - 1];
#endif
            for (int j = 0, i = pos + 1; i < encoded.Length; i++, j++)
            {
                int index = Array.IndexOf(Byteset, buffer[i]);
                if (index == -1)
                {
                    throw new FormatException("bech chars are out of range");
                }
                data[j] = (byte)index;
            }

            int[] error;
            if (!VerifyChecksum(data, encoded.Length, out encodingType, out error))
            {
                if (error == null || error.Length == 0)
                {
                    throw new FormatException("Error while verifying Bech32 checksum");
                }
                else
                {
                    throw new Bech32FormatException($"Error in Bech32 string at {String.Join(",", error)}", error);
                }
            }
#if HAS_SPAN
            return(data.Slice(0, data.Length - 6).ToArray());
#else
            return(data.Take(data.Length - 6).ToArray());
#endif
        }
Esempio n. 8
0
 public byte[] DecodeDataRaw(string encoded, out Bech32EncodingType encodingType)
 {
     return(DecodeDataCore(encoded, out encodingType));
 }
Esempio n. 9
0
 public virtual string EncodeData(byte[] data, int offset, int count, Bech32EncodingType encodingType)
Esempio n. 10
0
 private void CreateChecksum(ReadOnlySpan <byte> data, Bech32EncodingType encodingType, Span <byte> ret)
Esempio n. 11
0
 protected virtual bool VerifyChecksum(ReadOnlySpan <byte> data, int bechStringLen, out Bech32EncodingType encodingType, out int[] errorPosition)
Esempio n. 12
0
 protected virtual bool VerifyChecksum(byte[] data, int bechStringLen, out Bech32EncodingType encodingType, out int[] errorPosition)
 {
     return(VerifyChecksum(data.AsSpan(), bechStringLen, out encodingType, out errorPosition));
 }
Esempio n. 13
0
 static Bech32EncodingType()
 {
     BECH32  = new Bech32EncodingType(1);
     BECH32M = new Bech32EncodingType(0x2bc830a3);
     All     = new Bech32EncodingType[] { BECH32, BECH32M };
 }