Example #1
0
        /*public string GeneratePrivateViewKeyFromPrivateSpendKey(string spendPrivateKey)
         * {
         *  throw new NotImplementedException();
         * }
         *
         * public KeyPair GenerateViewKeysFromPrivateSpendKey(string spendPrivateKey)
         * {
         *  throw new NotImplementedException();
         * }*/

        public static void GenerateKeys(ref byte[] PublicKey, ref byte[] PrivateKey)
        {
            ge_p3      point = new ge_p3();
            HashBuffer k     = new HashBuffer();

            random_scalar(ref PrivateKey);
            ge_scalarmult_base(point, PrivateKey);
            ge_p3_tobytes(ref PublicKey, point);
        }
Example #2
0
        public static byte[] HashFromBranch(byte[][] Branch, int Depth, ref byte[] Leaf, ref byte[] Path)
        {
            // If depth is 0, the leaf hash is our root
            if (Depth == 0)
            {
                return(Leaf);
            }

            // Declare some variables
            HashBuffer Buffer   = new HashBuffer();
            bool       FromLeaf = true;

            // Loop until we are at root depth
            while (Depth > 0)
            {
                // Decrement depth
                Depth--;

                // Assign path values
                if (Path != null && (Path[Depth >> 3] & (1 << (Depth & 7))) != 0)
                {
                    if (FromLeaf)
                    {
                        Leaf     = Buffer.B;
                        FromLeaf = false;
                    }
                    else
                    {
                        Buffer.B = Keccak.KeccakHash(Buffer.Output);
                    }
                    Branch[Depth] = Buffer.A;
                }
                else
                {
                    if (FromLeaf)
                    {
                        Leaf     = Buffer.A;
                        FromLeaf = false;
                    }
                    else
                    {
                        Buffer.A = Keccak.KeccakHash(Buffer.Output);
                    }
                    Branch[Depth] = Buffer.B;
                }
            }

            // Perform final hashing
            return(Keccak.KeccakHash(Buffer.Output));
        }
Example #3
0
        /*public string SecretKeyToPublicKey(string privateKey)
         * {
         *  throw new NotImplementedException();
         * }
         *
         * public string GenerateKeyDerivation(string publicKey, string privateKey)
         * {
         *  throw new NotImplementedException();
         * }
         *
         * public string DerivePublicKey(string derivation, uint outputIndex, string publicKey)
         * {
         *  throw new NotImplementedException();
         * }
         *
         * public string DeriveSecretKey(string derivation, uint outputIndex, string privateKey)
         * {
         *  throw new NotImplementedException();
         * }
         *
         * public string UnderivePublicKey(string derivation, uint outputIndex, string derivedKey)
         * {
         *  throw new NotImplementedException();
         * }*/

        public static byte[] GenerateSignature(byte[] PrefixHash, byte[] PublicKey, byte[] PrivateKey)
        {
            // Create some ED25519 points
            ge_p3 Point     = new ge_p3();
            ge_p3 TestPoint = new ge_p3();

            // Declare a few more variables
            byte[] Comm     = new byte[32];
            byte[] Scalar   = new byte[32];
            byte[] SigBytes = new byte[64];

            // Verify private key
            if (sc_check(PrivateKey) != 0)
            {
                // Invalid secret key
                return(null);
            }

            // Verify public key
            ge_scalarmult_base(TestPoint, PrivateKey);
            byte[] Derived = new byte[32];
            ge_p3_tobytes(ref Derived, TestPoint);
            if (!PublicKey.Matches(Derived))
            {
                // Invalid public key
                return(null);
            }

            // Get a random scalar
            random_scalar(ref Scalar);

            // Convert scalar to bytes
            ge_scalarmult_base(Point, Scalar);
            ge_p3_tobytes(ref Comm, Point);

            // Combine hashes and get another scalar
            HashToScalar(ref SigBytes, PrefixHash.AppendBytes(PublicKey).AppendBytes(Comm));
            HashBuffer Signature = new HashBuffer()
            {
                A = SigBytes.SubBytes(0, 32),
                B = SigBytes.SubBytes(32, 32)
            };

            // Perform final math
            sc_mulsub(ref Signature.B, Signature.A, PrivateKey, Scalar);

            // Return output signature
            return(Signature.Output);
        }
Example #4
0
        public static bool CheckSignature(byte[] PrefixHash, byte[] PublicKey, byte[] Signature)
        {
            // Create some ED25519 points
            ge_p2 tmp2 = new ge_p2();
            ge_p3 tmp3 = new ge_p3();

            // Declare a few more variables
            byte[] Comm     = new byte[32];
            byte[] SigBytes = new byte[64];

            // Verify public key
            if (ge_frombytes_vartime(tmp3, PublicKey) != 0)
            {
                return(false);
            }

            // Create a signature buffer from the given signature
            HashBuffer Buffer = new HashBuffer(Signature);

            // Verify signature bytes
            if (sc_check(Buffer.A) != 0 || sc_check(Buffer.B) != 0)
            {
                return(false);
            }

            // Signature Part A
            ge_double_scalarmult_base_vartime(tmp2, Buffer.A, tmp3, Buffer.B);
            ge_tobytes(ref Comm, tmp2);

            // Combine hashes and convert to a scalar
            HashToScalar(ref SigBytes, PrefixHash.AppendBytes(PublicKey).AppendBytes(Comm));

            // Perform final math
            sc_sub(ref SigBytes, SigBytes, Signature);

            // Return result
            return(sc_isnonzero(SigBytes) == 0);
        }
Example #5
0
        public static bool CheckRingSignatures(byte[] PrefixHash, byte[] KeyImage, byte[][] PublicKeys, byte[][] Signatures)
        {
            // Convert signature list to signature buffer array
            HashBuffer[] SignaturesBuffer = new HashBuffer[Signatures.Length];
            for (int i = 0; i < SignaturesBuffer.Length; i++)
            {
                SignaturesBuffer[i] = new HashBuffer(Signatures[i]);
            }

            // Create some ED25519 points
            ge_p3   Image_Unp = new ge_p3();
            ge_dsmp Image_Pre = new ge_dsmp();

            // Declare a few more variables
            byte[] Sum  = new byte[32];
            byte[] Hash = new byte[32];

            // Create a signature buffer array
            HashBuffer[] Buffer = new HashBuffer[PublicKeys.Length];

            // Verify key image
            if (ge_frombytes_vartime(Image_Unp, KeyImage) != 0)
            {
                return(false);
            }

            // Precomp
            ge_dsm_precomp(ref Image_Pre, Image_Unp);

            // Another check
            if (ge_check_subgroup_precomp_vartime(Image_Pre) != 0)
            {
                return(false);
            }

            // Loop through all given signatures
            for (int i = 0; i < PublicKeys.Length; i++)
            {
                // Assign a new signature buffer
                Buffer[i] = new HashBuffer();

                // Create temporary points
                ge_p2 tmp2 = new ge_p2();
                ge_p3 tmp3 = new ge_p3();

                // Verify information
                if (sc_check(SignaturesBuffer[i].A) != 0 || sc_check(SignaturesBuffer[i].B) != 0)
                {
                    return(false);
                }
                if (ge_frombytes_vartime(tmp3, PublicKeys[i]) != 0)
                {
                    return(false);
                }

                // Signature Part A
                ge_double_scalarmult_base_vartime(tmp2, SignaturesBuffer[i].A, tmp3, SignaturesBuffer[i].B);
                ge_tobytes(ref Buffer[i].A, tmp2);

                // Convert public key to elliptic curve point
                HashToEllipticCurve(tmp3, PublicKeys[i]);

                // Signature Part B
                ge_double_scalarmult_precomp_vartime(tmp2, SignaturesBuffer[i].B, tmp3, SignaturesBuffer[i].A, Image_Pre);
                ge_tobytes(ref Buffer[i].B, tmp2);

                // Add to sum
                sc_add(ref Sum, Sum, SignaturesBuffer[i].A);
            }

            // Combine buffer and convert to a scalar
            byte[] SigHash = PrefixHash;
            for (int i = 0; i < Buffer.Length; i++)
            {
                SigHash = SigHash.AppendBytes(Buffer[i].Output);
            }
            HashToScalar(ref Hash, SigHash);

            // Perform final math
            sc_sub(ref Hash, Hash, Sum);

            // Return result of final check
            return(sc_isnonzero(Hash) == 0);
        }
Example #6
0
        public static byte[][] GenerateRingSignatures(byte[] PrefixHash, byte[] KeyImage, byte[][] PublicKeys, byte[] TransactionSecretKey, ulong RealOutput)
        {
            // Create some ED25519 points
            ge_p3   Image_Unp = new ge_p3();
            ge_dsmp Image_Pre = new ge_dsmp();

            // Declare a few more variables
            byte[] Sum    = new byte[32];
            byte[] Scalar = new byte[32];
            byte[] Hash   = new byte[32];

            // Create a signature buffer array and output array
            HashBuffer[] Buffer     = new HashBuffer[PublicKeys.Length];
            HashBuffer[] Signatures = new HashBuffer[PublicKeys.Length];

            // Verify key image
            if (ge_frombytes_vartime(Image_Unp, KeyImage) != 0)
            {
                return(null);
            }

            // Precomp
            ge_dsm_precomp(ref Image_Pre, Image_Unp);

            // Loop through all given keys
            for (ulong i = 0; i < (ulong)PublicKeys.Length; i++)
            {
                // Assign a new signature buffers
                Buffer[i]     = new HashBuffer();
                Signatures[i] = new HashBuffer();

                // Create temporary points
                ge_p2 tmp2 = new ge_p2();
                ge_p3 tmp3 = new ge_p3();

                // This is the real output index
                if (i == RealOutput)
                {
                    // Generate a random scalar
                    random_scalar(ref Scalar);
                    //random_scalar(k);

                    ge_scalarmult_base(tmp3, Scalar);
                    //ge_scalarmult_base(tmp3, k);

                    // Signature Part A
                    ge_p3_tobytes(ref Buffer[i].A, tmp3);
                    //ge_p3_tobytes(reinterpret_cast < unsigned char *> (&buf->ab[i].a), &tmp3);

                    // Turn public key at this index into an elliptic curve, then multiply
                    HashToEllipticCurve(tmp3, PublicKeys[i]);
                    //hash_to_ec(publicKeys[i], tmp3);

                    ge_scalarmult(tmp2, Scalar, tmp3);
                    //ge_scalarmult(&tmp2, reinterpret_cast < unsigned char *> (&k), &tmp3);

                    // Signature Part B
                    ge_tobytes(ref Buffer[i].B, tmp2);
                    // ge_tobytes(reinterpret_cast < unsigned char *> (&buf->ab[i].b), &tmp2);
                }

                // This is a generated signature index
                else
                {
                    // Create a random scalar for both signature parts
                    random_scalar(ref Signatures[i].A);
                    random_scalar(ref Signatures[i].B);

                    // Get bytes from this public key (also verifies it)
                    if (ge_frombytes_vartime(tmp3, PublicKeys[i]) != 0)
                    {
                        return(null);
                    }

                    // Signature Part A
                    ge_double_scalarmult_base_vartime(tmp2, Signatures[i].A, tmp3, Signatures[i].B);
                    ge_tobytes(ref Buffer[i].A, tmp2);

                    // Convert public key to elliptic curve point
                    HashToEllipticCurve(tmp3, PublicKeys[i]);

                    // Signature Part B
                    ge_double_scalarmult_precomp_vartime(tmp2, Signatures[i].B, tmp3, Signatures[i].A, Image_Pre);
                    ge_tobytes(ref Buffer[i].B, tmp2);

                    // Add to sum
                    sc_add(ref Sum, Sum, Signatures[i].A);
                }
            }

            // Combine buffer and convert to a scalar
            byte[] SigHash = PrefixHash;
            for (int i = 0; i < Buffer.Length; i++)
            {
                SigHash = SigHash.AppendBytes(Buffer[i].Output);
            }
            HashToScalar(ref Hash, SigHash);

            // Perform final math
            sc_sub(ref Signatures[RealOutput].A, Hash, Sum);
            sc_mulsub(ref Signatures[RealOutput].B, Signatures[RealOutput].A, TransactionSecretKey, Scalar);

            // Create an output array and return it
            byte[][] Output = new byte[Signatures.Length][];
            for (int i = 0; i < Signatures.Length; i++)
            {
                Output[i] = Signatures[i].Output;
            }
            return(Output);
        }