private static CombinedSecret Combine(IEnumerable <SecretShare> shares, Diffuser diffuser)
        {
            var allShares = shares.ToArray();

            if (allShares.Length == 0)
            {
                throw new SecretSplitterException("You must provide at least one secret share (piece).");
            }

            var expectedShareType = allShares[0].ShareType;

            if (!allShares.All(s => s.ShareType == expectedShareType))
            {
                throw new SecretSplitterException("Secret shares (pieces) must be be of the same type.");
            }

            var firstInvalidShare = allShares.FirstOrDefault(s => (s.ShareType != SecretShareType.Unknown) && !s.HasValidChecksum);

            if (firstInvalidShare != null)
            {
                throw new InvalidChecksumShareException(firstInvalidShare.ParsedValue);
            }

            var secretCoefficient = LagrangeInterpolator.EvaluateAtZero(allShares.Select(s => s.Point));
            var scrambledValue    = secretCoefficient.PolynomialValue;
            var unscrambledValue  = diffuser.Unscramble(scrambledValue, scrambledValue.ToByteArray().Length);
            var recoveredSecret   = unscrambledValue.ToUnsignedBigEndianBytes();

            return(new CombinedSecret(allShares[0].ShareType, recoveredSecret));
        }
Exemple #2
0
        public static byte[] Combine(IEnumerable <FiniteFieldPoint> points)
        {
            var allShares = points.ToArray();

            if (allShares.Length == 0)
            {
                throw new ArgumentException("You must provide at least one secret share (piece).", nameof(points));
            }

            var secretCoefficient = LagrangeInterpolator.EvaluateAtZero(allShares);
            var scrambledValue    = secretCoefficient.PolynomialValue;
            var unscrambledValue  = DefaultDiffuser.Unscramble(scrambledValue, scrambledValue.ToByteArray().Length);

            return(unscrambledValue.ToUnsignedBigEndianBytes());
        }
Exemple #3
0
        private static CombinedSecret Combine(IEnumerable <SecretShare> shares, Diffuser diffuser)
        {
            var allShares = shares.ToArray();

            if (allShares.Length == 0)
            {
                throw new SecretSplitterException("You must provide at least one secret share (piece).");
            }

            int expectedShareLength = allShares[0].ParsedValue.Substring(allShares[0].ParsedValue.LastIndexOf('-') + 1).Length;

            if (!allShares.All(s => s.ParsedValue.Substring(s.ParsedValue.LastIndexOf('-') + 1).Length == expectedShareLength))
            {
                throw new SecretSplitterException("Secret shares (pieces) must be be of the same size.");
            }

            var expectedShareType = allShares[0].ShareType;

            if (!allShares.All(s => s.ShareType == expectedShareType))
            {
                throw new SecretSplitterException("Secret shares (pieces) must be be of the same type.");
            }

            var firstInvalidShare = allShares.FirstOrDefault(s => (s.ShareType != SecretShareType.Unknown) && !s.HasValidChecksum);

            if (firstInvalidShare != null)
            {
                throw new InvalidChecksumShareException(firstInvalidShare.ParsedValue);
            }

            var secretCoefficient = LagrangeInterpolator.EvaluateAtZero(allShares.Select(s => s.Point));
            var scrambledValue    = secretCoefficient.PolynomialValue;
            var unscrambledValue  = diffuser.Unscramble(scrambledValue, expectedShareLength / 2);
            var recoveredSecret   = unscrambledValue.ToUnsignedBigEndianBytes();

            int paddingNeeded = expectedShareLength / 2 - recoveredSecret.Length;

            if (paddingNeeded > 0)
            {
                var padBytes = new byte[paddingNeeded];
                var newArray = new byte[paddingNeeded + recoveredSecret.Length];
                Array.Copy(padBytes, 0, newArray, 0, paddingNeeded);
                Array.Copy(recoveredSecret, 0, newArray, paddingNeeded, recoveredSecret.Length);
                recoveredSecret = newArray;
            }

            return(new CombinedSecret(allShares[0].ShareType, recoveredSecret));
        }