public static SplitSecret Split(SecretShareType shareType, byte[] secret, int threshold, Diffuser diffuser)
        {
            var irreduciblePolynomial = IrreduciblePolynomial.CreateOfByteSize(secret.Length);
            var rawSecret = secret.ToBigIntegerFromBigEndianUnsignedBytes();
            var diffusedSecret = diffuser.Scramble(rawSecret, secret.Length);
            var secretCoefficient = new FiniteFieldPolynomial(irreduciblePolynomial, diffusedSecret);

            var allCoefficients = new[] { secretCoefficient }
                .Concat(
                    GetRandomPolynomials(
                        irreduciblePolynomial,
                        threshold - 1)
                )
                .ToArray();

            var passPhrase = new SecureString();

            try {
                foreach (var currentChar in secret.ToHexString()) {
                    passPhrase.AppendChar(currentChar);
                }
            }
            catch {
                passPhrase = null;
            }

            if((passPhrase == null) || (passPhrase.Length == 0)) {
                passPhrase = null;
            }

            return new SplitSecret(shareType, threshold, irreduciblePolynomial, allCoefficients, passPhrase);
        }
Beispiel #2
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).");
            }

            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));
        }
 // Keeping the methods that take a Diffuser as private to simplify API for now
 private static string[] SplitMessage(string secret, int threshold, int totalShares, Diffuser diffuser) {
     return
         Split(SecretShareType.Message, SecretEncoder.EncodeString(secret), threshold, diffuser)
         .GetShares(totalShares)
         .Select(share => share.ToString())
         .ToArray();
 }
Beispiel #4
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));
        }
        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);
        }
Beispiel #6
0
 public static CombinedSecret Combine(IEnumerable <string> allShares, Diffuser diffuser)
 {
     return(Combine(allShares.Select(share => Regex.Match(share, SecretShare.RegexPattern).Value).Select(SecretShare.Parse), diffuser));
 }
 public static CombinedSecret Combine(IEnumerable<string> allShares, Diffuser diffuser) {
     return Combine(allShares.Select(share => Regex.Match(share, SecretShare.RegexPattern).Value).Select(SecretShare.Parse), diffuser);
 }
Beispiel #8
0
        public static SplitSecret Split(SecretShareType shareType, byte[] secret, int threshold, Diffuser diffuser)
        {
            var irreduciblePolynomial = IrreduciblePolynomial.CreateOfByteSize(secret.Length);
            var rawSecret             = secret.ToBigIntegerFromBigEndianUnsignedBytes();
            var diffusedSecret        = diffuser.Scramble(rawSecret, secret.Length);
            var secretCoefficient     = new FiniteFieldPolynomial(irreduciblePolynomial, diffusedSecret);

            var allCoefficients = new[] { secretCoefficient }
            .Concat(
                GetRandomPolynomials(
                    irreduciblePolynomial,
                    threshold - 1)
                )
            .ToArray();

            var passPhrase = new SecureString();

            try {
                foreach (var currentChar in secret.ToHexString())
                {
                    passPhrase.AppendChar(currentChar);
                }
            }
            catch {
                passPhrase = null;
            }

            if ((passPhrase == null) || (passPhrase.Length == 0))
            {
                passPhrase = null;
            }

            return(new SplitSecret(shareType, threshold, irreduciblePolynomial, allCoefficients, passPhrase));
        }
Beispiel #9
0
 // Keeping the methods that take a Diffuser as private to simplify API for now
 private static string[] SplitMessage(string secret, int threshold, int totalShares, Diffuser diffuser)
 {
     return
         (Split(SecretShareType.Message, SecretEncoder.EncodeString(secret), threshold, diffuser)
          .GetShares(totalShares)
          .Select(share => share.ToString())
          .ToArray());
 }