Пример #1
0
        /// <summary>读取密钥</summary>
        /// <param name="file">文件</param>
        /// <param name="generate">是否生成</param>
        /// <returns></returns>
        public Boolean ReadKey(String file, Boolean generate = false)
        {
            if (file.IsNullOrEmpty())
            {
                return(false);
            }

            file = file.GetFullPath();
            if (File.Exists(file))
            {
                Key = File.ReadAllText(file);

                if (!Key.IsNullOrEmpty())
                {
                    return(true);
                }
            }

            if (!generate || !file.EndsWithIgnoreCase(".prvkey"))
            {
                return(false);
            }

            var ss = DSAHelper.GenerateKey();

            File.WriteAllText(file.EnsureDirectory(true), ss[0]);
            file = Path.ChangeExtension(file, ".pubkey");
            File.WriteAllText(file, ss[1]);

            Key = ss[0];

            return(true);
        }
Пример #2
0
        /// <summary>编码用户和有效期得到令牌</summary>
        /// <param name="user">用户</param>
        /// <param name="expire">有效期</param>
        /// <returns></returns>
        public String Encode(String user, DateTime expire)
        {
            if (user.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(user));
            }
            if (expire.Year < 2000)
            {
                throw new ArgumentOutOfRangeException(nameof(expire));
            }
            if (Key.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(Key));
            }

            var dt   = new DateTime(1970, 1, 1);
            var secs = (Int32)(expire - dt).TotalSeconds;

            // 拼接数据并签名
            var data = (user + "," + secs).GetBytes();
            var sig  = DSAHelper.Sign(data, Key);

            // Base64拼接数据和签名
            return(data.ToUrlBase64() + "." + sig.ToUrlBase64());
        }
 private byte[] SignData(byte[] data)
 {
     using (var dsa = DSAHelper.GetPrivateDsa())
     {
         var result = dsa.CreateSignature(data);
         return(result);
     }
 }
Пример #4
0
        private void btnDSA_Click(Object sender, EventArgs e)
        {
            var buf = GetBytes();
            var key = rtPass.Text;

            if (key.Length < 100)
            {
                key         = DSAHelper.GenerateKey().First();
                rtPass.Text = key;
            }

            buf = DSAHelper.Sign(buf, key);

            SetResult(buf);
        }
Пример #5
0
        private void btnDSA_Click(Object sender, EventArgs e)
        {
            var buf = GetBytes();
            var key = rtPass.Text;

            if (key.Length < 100)
            {
                key         = DSAHelper.GenerateKey().First();
                rtPass.Text = key;
            }

            buf = DSAHelper.Sign(buf, key);

            rtResult.Text = buf.ToHex() + Environment.NewLine + Environment.NewLine + buf.ToBase64();
        }
Пример #6
0
        /// <summary>
        /// B.1.1 from FIPS 186-4. This is equivalent to B.1.2, the other KeyGeneration method.
        /// </summary>
        /// <param name="domainParameters"></param>
        /// <returns></returns>
        public FfcKeyPairGenerateResult GenerateKeyPair(FfcDomainParameters domainParameters)
        {
            var L = new BitString(domainParameters.P).BitLength;
            var N = new BitString(domainParameters.Q).BitLength;

            // Shouldn't really be necessary but just in case
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new FfcKeyPairGenerateResult("Invalid L, N pair"));
            }

            var rand = new Random800_90();
            var c    = rand.GetRandomBitString(N + 64).ToPositiveBigInteger();

            var x = (c % (domainParameters.Q - 1)) + 1;
            var y = BigInteger.ModPow(domainParameters.G, x, domainParameters.P);

            return(new FfcKeyPairGenerateResult(new FfcKeyPair(x, y)));
        }
        public bool Verify(string incoming)
        {
            var data      = Convert.FromBase64String(incoming);
            var json      = _encoding.GetString(data);
            var dic       = JsonConvert.DeserializeObject <Dictionary <string, string> >(json);
            var rgb       = Convert.FromBase64String(dic["rgb"]);
            var signature = Convert.FromBase64String(dic["signature"]);
            var ownedRgb  = ComposeData();

            if (!IsArraySame(rgb, ownedRgb))
            {
                return(false);
            }

            using (var dsa = DSAHelper.GetPublicDsa())
            {
                return(dsa.VerifySignature(rgb, signature));
            }
        }
Пример #8
0
        /// <summary>
        /// A.1.2.1.1 Get a first seed value
        /// </summary>
        /// <param name="N"></param>
        /// <param name="seedLen"></param>
        /// <returns></returns>
        private BigInteger GetFirstSeed(int L, int N, int seedLen)
        {
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(0);
            }

            if (seedLen < N)
            {
                return(0);
            }

            BitString firstSeed;

            do
            {
                firstSeed = _entropy.GetEntropy(seedLen);
            } while (firstSeed.ToPositiveBigInteger() < NumberTheory.Pow2(N - 1));

            return(firstSeed.ToPositiveBigInteger());
        }
Пример #9
0
        /// <summary>尝试解码令牌,即使失败,也会返回用户信息和有效时间</summary>
        /// <param name="token">令牌</param>
        /// <param name="user">用户信息</param>
        /// <param name="expire">有效时间</param>
        /// <returns>解码结果,成功或失败</returns>
        public Boolean TryDecode(String token, out String user, out DateTime expire)
        {
            if (token.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(token));
            }
            if (Key.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(Key));
            }

            user   = null;
            expire = DateTime.MinValue;

            // Base64拆分数据和签名
            var p    = token.IndexOf('.');
            var data = token.Substring(0, p).ToBase64();
            var sig  = token.Substring(p + 1).ToBase64();

            // 拆分数据和有效期
            var str = data.ToStr();

            p = str.LastIndexOf(',');

            user = str.Substring(0, p);
            var secs = str.Substring(p + 1).ToInt();

            expire = secs.ToDateTime();

            // 验证签名
            //if (!DSAHelper.Verify(data, Key, sig)) throw new InvalidOperationException("签名验证失败!");
            if (!DSAHelper.Verify(data, Key, sig))
            {
                return(false);
            }

            return(true);
        }
Пример #10
0
        /// <summary>令牌解码得到用户和有效期</summary>
        /// <param name="token">令牌</param>
        /// <param name="expire">有效期</param>
        /// <returns></returns>
        public String Decode(String token, out DateTime expire)
        {
            if (token.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(token));
            }
            if (Key.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(Key));
            }
            expire = DateTime.MinValue;

            // Base64拆分数据和签名
            var p    = token.IndexOf('.');
            var data = token.Substring(0, p).ToBase64();
            var sig  = token.Substring(p + 1).ToBase64();

            // 验证签名
            //if (!DSAHelper.Verify(data, Key, sig)) throw new InvalidOperationException("签名验证失败!");
            if (!DSAHelper.Verify(data, Key, sig))
            {
                return(null);
            }

            // 拆分数据和有效期
            var str = data.ToStr();

            p = str.LastIndexOf(',');

            var user = str.Substring(0, p);
            var secs = str.Substring(p + 1).ToInt();

            expire = new DateTime(1970, 1, 1).AddSeconds(secs);

            return(user);
        }
Пример #11
0
        private void btnDSA2_Click(Object sender, EventArgs e)
        {
            var buf  = GetBytes();
            var pass = rtPass.Text;

            var v = rtResult.Text;

            if (v.Contains("\n\n"))
            {
                v = v.Substring(null, "\n\n");
            }
            var sign = GetBytes(v);

            var rs = DSAHelper.Verify(buf, pass, sign);

            if (rs)
            {
                MessageBox.Show("验证通过", "DSA数字签名", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("验证失败", "DSA数字签名", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Пример #12
0
        private void btnDSA2_Click(Object sender, EventArgs e)
        {
            var buf  = GetBytes();
            var pass = rtPass.Buffer.Text;

            var v = rtResult.Buffer.Text;

            if (v.Contains("\n\n"))
            {
                v = v.Substring(null, "\n\n");
            }
            var sign = GetBytes(v);

            var rs = DSAHelper.Verify(buf, pass, sign);

            if (rs)
            {
                MessageBox.Show("DSA数字签名验证通过");
            }
            else
            {
                MessageBox.Show("DSA数字签名验证失败");
            }
        }
Пример #13
0
        /// <summary>
        /// A.1.2.1.2
        /// </summary>
        /// <param name="L"></param>
        /// <param name="N"></param>
        /// <param name="firstSeed"></param>
        /// <returns></returns>
        private PQGenerateResult Generate(int L, int N, BigInteger firstSeed)
        {
            // 1
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQGenerateResult("Bad L, N pair"));
            }

            // 2
            var qResult = PrimeGen186_4.ShaweTaylorRandomPrime(N, firstSeed, _sha);

            if (!qResult.Success)
            {
                return(new PQGenerateResult("Failed to generate q from ShaweTaylor"));
            }
            var q        = qResult.Prime;
            var qSeed    = qResult.PrimeSeed;
            var qCounter = qResult.PrimeGenCounter;

            // 3
            var pLen    = L.CeilingDivide(2) + 1;
            var pResult = PrimeGen186_4.ShaweTaylorRandomPrime(pLen, qSeed, _sha);

            if (!pResult.Success)
            {
                return(new PQGenerateResult("Failed to generate p0 from ShaweTaylor"));
            }
            var p0       = pResult.Prime;
            var pSeed    = pResult.PrimeSeed;
            var pCounter = pResult.PrimeGenCounter;

            // 4, 5
            var outLen     = _sha.HashFunction.OutputLen;
            var iterations = L.CeilingDivide(outLen) - 1;
            var oldCounter = pCounter;

            // 6, 7
            BigInteger x = 0;

            for (var i = 0; i <= iterations; i++)
            {
                x += _sha.HashNumber(pSeed + i).ToBigInteger() * NumberTheory.Pow2(i * outLen);
            }

            // 8
            pSeed += iterations + 1;

            // 9
            x = NumberTheory.Pow2(L - 1) + (x % NumberTheory.Pow2(L - 1));

            // 10
            var t = x.CeilingDivide(2 * q * p0);

            do
            {
                // 11
                if (2 * t * q * p0 + 1 > NumberTheory.Pow2(L))
                {
                    t = NumberTheory.Pow2(L - 1).CeilingDivide(2 * q * p0);
                }

                // 12, 13
                var p = 2 * t * q * p0 + 1;
                pCounter++;

                // 14, 15
                BigInteger a = 0;
                for (var i = 0; i <= iterations; i++)
                {
                    a += _sha.HashNumber(pSeed + i).ToBigInteger() * NumberTheory.Pow2(i * outLen);
                }

                // 16
                pSeed += iterations + 1;

                // 17
                a = 2 + (a % (p - 3));

                // 18
                var z = BigInteger.ModPow(a, 2 * t * q, p);

                // 19
                if (1 == NumberTheory.GCD(z - 1, p) && 1 == BigInteger.ModPow(z, p0, p))
                {
                    return(new PQGenerateResult(p, q, new DomainSeed(firstSeed, pSeed, qSeed), new Counter(pCounter, qCounter)));
                }

                // 20
                if (pCounter > 4 * L + oldCounter)
                {
                    return(new PQGenerateResult("Too many iterations"));
                }

                // 21
                t++;

                // 22
            } while (true);
        }
Пример #14
0
        /// <summary>
        /// A.1.2.2
        /// </summary>
        /// <param name="p"></param>
        /// <param name="q"></param>
        /// <param name="seed"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public PQValidateResult Validate(BigInteger p, BigInteger q, DomainSeed seed, Counter count)
        {
            // 0, domain type check
            if (seed.Mode != PrimeGenMode.Provable && count.Mode != PrimeGenMode.Provable)
            {
                return(new PQValidateResult("Invalid DomainSeed and Counter"));
            }

            // 1, 2
            var L = new BitString(p).BitLength;
            var N = new BitString(q).BitLength;

            // 3
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQValidateResult("Invalid L, N pair"));
            }

            // 4
            if (seed.Seed < NumberTheory.Pow2(N - 1))
            {
                return(new PQValidateResult("Bad first seed"));
            }

            // 5
            if (NumberTheory.Pow2(N) <= q)
            {
                return(new PQValidateResult("Bad q, too small"));
            }

            // 6
            if (NumberTheory.Pow2(L) <= p)
            {
                return(new PQValidateResult("Bad p, too large"));
            }

            // 7
            if ((p - 1) % q != 0)
            {
                return(new PQValidateResult("p - 1 % q != 0, bad values"));
            }

            // 8
            var computed_result = Generate(L, N, seed.Seed);

            if (!computed_result.Success)
            {
                return(new PQValidateResult("Failed to generate p and q"));
            }

            if (q != computed_result.Q || seed.QSeed != computed_result.Seed.QSeed || count.QCount != computed_result.Count.QCount)
            {
                return(new PQValidateResult("Failed to generate given q"));
            }

            if (p != computed_result.P || seed.PSeed != computed_result.Seed.PSeed || count.PCount != computed_result.Count.PCount)
            {
                return(new PQValidateResult("Failed to generate given p"));
            }

            return(new PQValidateResult());
        }
Пример #15
0
        /// <summary>
        /// A.1.1.2 from FIPS 186-4
        /// </summary>
        /// <param name="L"></param>
        /// <param name="N"></param>
        /// <param name="seedLen"></param>
        /// <returns></returns>
        public PQGenerateResult Generate(int L, int N, int seedLen)
        {
            // 1. Check L/N pair
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQGenerateResult("Invalid L, N pair"));
            }

            // 2. Check seedLen
            if (seedLen < N)
            {
                return(new PQGenerateResult("Invalid seedLen"));
            }

            // 3, 4 Compute n, b
            var outLen = _sha.HashFunction.OutputLen;
            var n      = L.CeilingDivide(outLen) - 1;
            var b      = L - 1 - (n * outLen);

            do
            {
                BigInteger seed, q;

                do
                {
                    // 5. Get random seed
                    seed = _entropy.GetEntropy(seedLen).ToPositiveBigInteger();

                    // 6. Hash seed
                    var U = _sha.HashNumber(seed).ToBigInteger() % NumberTheory.Pow2(N - 1);

                    // 7. Compute q
                    q = NumberTheory.Pow2(N - 1) + U + 1 - (U % 2);

                    // Check if q is prime, if not go back to 5, assume highest security strength
                } while (!NumberTheory.MillerRabin(q, DSAHelper.GetMillerRabinIterations(L, N)));

                // 10, 11 Compute p
                var offset     = 1;
                var upperBound = (4 * L - 1);
                for (var ctr = 0; ctr <= upperBound; ctr++)
                {
                    // 11.1, 11.2
                    var W = _sha.HashNumber(seed + offset).ToBigInteger();
                    for (var j = 1; j < n; j++)
                    {
                        W += _sha.HashNumber(seed + offset + j).ToBigInteger() * NumberTheory.Pow2(j * outLen);
                    }
                    W += (_sha.HashNumber(seed + offset + n).ToBigInteger() % NumberTheory.Pow2(b)) * NumberTheory.Pow2(n * outLen);

                    // 11.3
                    var X = W + NumberTheory.Pow2(L - 1);

                    // 11.4
                    var c = X % (2 * q);

                    // 11.5
                    var p = X - (c - 1);

                    // 11.6, 11.7, 11.8
                    if (p >= NumberTheory.Pow2(L - 1))
                    {
                        // Check if p is prime, if so return
                        if (NumberTheory.MillerRabin(p, DSAHelper.GetMillerRabinIterations(L, N)))
                        {
                            return(new PQGenerateResult(p, q, new DomainSeed(seed), new Counter(ctr)));
                        }
                    }

                    // 11.9
                    offset += n + 1;
                }

                // 12
            } while (true);
        }
Пример #16
0
        /// <summary>
        /// A.1.1.3 from FIPS 186-4
        /// </summary>
        /// <param name="p"></param>
        /// <param name="q"></param>
        /// <param name="seed"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public PQValidateResult Validate(BigInteger p, BigInteger q, DomainSeed seed, Counter count)
        {
            if (seed.Mode != PrimeGenMode.Probable && count.Mode != PrimeGenMode.Probable)
            {
                return(new PQValidateResult("Invalid DomainSeed and Counter"));
            }

            // 1, 2
            var L = new BitString(p).BitLength;
            var N = new BitString(q).BitLength;

            // 3
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQValidateResult("Invalid L, N pair"));
            }

            // 4
            if (count.Count > (4 * L - 1))
            {
                return(new PQValidateResult("Invalid counter"));
            }

            // 5, 6

            /*
             *  Appending 0s to the bitstring representation of the seed as to make it mod 32 (if it isn't already), as this is the mod of the original seed that is hashed.
             *  In instances (as an example) when the chosen seed starts with eight zero bits in a row, the biginteger representation of said bitstring is 1 byte smaller than it should be,
             *  thus failing the check that it is at least the length of N
             */
            var seedBitString = new BitString(seed.Seed);

            if (seedBitString.BitLength % 32 != 0)
            {
                seedBitString = BitString.ConcatenateBits(BitString.Zeroes(32 - seedBitString.BitLength % 32), seedBitString);
            }
            var seedLen = seedBitString.BitLength;

            if (seedLen < N)
            {
                return(new PQValidateResult("Invalid seed"));
            }

            // 7
            var U = _sha.HashNumber(seed.Seed).ToBigInteger() % NumberTheory.Pow2(N - 1);

            // 8
            var computed_q = NumberTheory.Pow2(N - 1) + U + 1 - (U % 2);

            // 9
            if (!NumberTheory.MillerRabin(computed_q, DSAHelper.GetMillerRabinIterations(L, N)) || computed_q != q)
            {
                return(new PQValidateResult("Q not prime, or doesn't match expected value"));
            }

            // 10, 11, 12
            var outLen = _sha.HashFunction.OutputLen;
            var n      = L.CeilingDivide(outLen) - 1;
            var b      = L - 1 - (n * outLen);
            var offset = 1;

            // 13
            BigInteger computed_p = 0;
            int        i;

            for (i = 0; i <= count.Count; i++)
            {
                // 13.1, 13.2
                var W = _sha.HashNumber(seed.Seed + offset).ToBigInteger();
                for (var j = 1; j < n; j++)
                {
                    W += (_sha.HashNumber(seed.Seed + offset + j).ToBigInteger()) * NumberTheory.Pow2(j * outLen);
                }
                W += ((_sha.HashNumber(seed.Seed + offset + n).ToBigInteger()) % NumberTheory.Pow2(b)) * NumberTheory.Pow2(n * outLen);

                // 13.3
                var X = W + NumberTheory.Pow2(L - 1);

                // 13.4
                var c = X % (2 * q);

                // 13.5
                computed_p = X - (c - 1);

                // 13.6, 13.7, 13.8
                if (computed_p >= NumberTheory.Pow2(L - 1))
                {
                    // Check if p is prime, if so return
                    if (NumberTheory.MillerRabin(computed_p, DSAHelper.GetMillerRabinIterations(L, N)))
                    {
                        break;
                    }
                }

                // 13.9
                offset += n + 1;
            }

            // 14
            if (i != count.Count || computed_p != p || !NumberTheory.MillerRabin(computed_p, DSAHelper.GetMillerRabinIterations(L, N)))
            {
                return(new PQValidateResult($"Invalid p value or counter. computed_p = {new BitString(computed_p).ToHex()}"));
            }

            // 15
            return(new PQValidateResult());
        }