Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to print Der value from signature #27

Open
smartkodian opened this issue May 14, 2022 · 3 comments
Open

How to print Der value from signature #27

smartkodian opened this issue May 14, 2022 · 3 comments

Comments

@smartkodian
Copy link

smartkodian commented May 14, 2022

Hi,

I am using this command to show Der value but doesn't work with me, Any help please?

PrivateKey privateKey = PrivateKey.fromPem(privateKeyPem);
Signature signatures = Ecdsa.sign(message, privateKey);
byte[] der = signatures.toDer();
Console.WriteLine(der);

@smartkodian smartkodian changed the title How to print Der text How to print Der value from signature May 14, 2022
@softwarekamal
Copy link

softwarekamal commented May 18, 2022

Hello @smartkodian, You can use Convert.ToBase64(der), or BitConverter.ToString(der).Replace("-", "")

I wish they can support P1363 format! short signature like Bouncy Castle SHA256WithPlain-ECDSA
Because for 256 bit curves. library default output are ASN1 = 70-71, while P1363 are fixed size. 64 byte. That's it! But not implemented 😞

But I try to do manually. It worked for sign, But can't verified! because library only verify ASN1 DER. I don't know how to apply it. Am sad my friend no community to support us, we can cry together.... 😭

        var signature = EllipticCurve.Ecdsa.sign("hello dear", privateKey);
            var signatureBytes = signature.toDer();

            Tuple<byte[], byte[]> tuple = Der.removeSequence(signatureBytes);
      
            Tuple<BigInteger, byte[]> tuple2 = Der.removeInteger(tuple.Item1);
            Tuple<BigInteger, byte[]> tuple3 = Der.removeInteger(tuple2.Item2);
            
            var byte1 = tuple2.Item1.ToByteArray().Reverse().ToArray(); // O
            var byte2 = tuple3.Item1.ToByteArray().Reverse().ToArray();
            var P1363ShortSignature = byte1.Concat(byte2).ToArray();

@smartkodian
Copy link
Author

Hello @softwarekamal yes bro, Actually I faced the issue with 64 byte issue in starkbank library but now I am testing on PHP and I am using openssl_sign beside checking the 32 byte for R and S value but I have problem with ECDSA signature format. Can we contact?

@softwarekamal
Copy link

softwarekamal commented May 18, 2022

Welcome back @smartkodian,
Do you try Bouncy Castle?, If you need already defined curves Bouncy Castle are very good. But I can't use custom curves with it. There's another library Called Ecc, Its do the short fixed signature, for example 256 will give exactly 64 Bytes. You can try it. But its not give extra padding like current hard-coded library 💯

Ccrrent library ecdsa-dotnet need more extension methods to make it beautiful like:
EllipticCurve.Ecdsa.FromShortDer(), EllipticCurve.Ecdsa.ToShortDer(), If you have any custom implementation you can share it 🥇
I wish you tell me what other libraries you can use for custom curves. Because I can't use Bouncy Castle for custom curves.

I will share you my bouncy castle ECDSA class that give fixed 64 bytes length:
Note: you must download Bouncy Castle Nuget

using System;
using System.Text;
using System.IO;

using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;

namespace ECDSABouncy
{
    public static class ECDSAEncryption
    {
        /// <summary>
        /// Get private or public <see cref="AsymmetricKeyParameter"/> from PEM key format,
        /// </summary>
        private static AsymmetricKeyParameter GetAsymmetricKeyParameter(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (!key.Trim().StartsWith("-----BEGIN "))
                throw new ArgumentException("Given key doesn't start with -----BEGIN, Key must be in PEM format");

            using (StringReader reader = new StringReader(key))
            {
                PemReader pemReader = new PemReader(reader);
                if (key.Trim().EndsWith("PRIVATE KEY-----"))
                    return ((AsymmetricCipherKeyPair)pemReader.ReadObject()).Private;
                return (AsymmetricKeyParameter)pemReader.ReadObject();
            }
        }

        /// <summary>
        /// Generate ECDSA key pair. Allowed key sizes: 192, 224, 239, 256, 384, 521
        /// </summary>
        public static (string privateKey, string publicKey) GenerateRandomKeys(int keySize = 256)
        {
            ECKeyPairGenerator keyGenerator = new ECKeyPairGenerator();
            keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), keySize));
            AsymmetricCipherKeyPair keyPair = keyGenerator.GenerateKeyPair();
            string privateKey, publicKey;
            
            using (StringWriter writer = new StringWriter())
            {
                PemWriter pemWriter = new PemWriter(writer);
                pemWriter.WriteObject(keyPair.Private);
                privateKey = writer.ToString().Trim();

                writer.GetStringBuilder().Clear();
                pemWriter.WriteObject(keyPair.Public);
                publicKey = writer.ToString().Trim();
            }
            return (privateKey, publicKey);
        }

        /// <summary>
        /// Generate ECDSA signature of <paramref name="message"/> with given <paramref name="privateKey"/>.
        /// </summary>
        public static byte[] GenerateSignature(byte[] message, string privateKey)
        {
            if (message == null || message.Length == 0)
                throw new ArgumentException("message can't be null or zero length", nameof(message));

            AsymmetricKeyParameter keyParameter = GetAsymmetricKeyParameter(privateKey);
            ISigner sign = SignerUtilities.GetSigner("SHA256WithPlain-ECDSA");
            sign.Init(true, keyParameter);
            sign.BlockUpdate(message, 0, message.Length);
            byte[] signedBytes = sign.GenerateSignature();
            return signedBytes;
        }

        /// <summary>
        /// Generate ECDSA signature of <paramref name="message"/> with given <paramref name="privateKey"/>.
        /// </summary>
        public static string GenerateSignature(string message, string privateKey)
        {
            byte[] signedBytes = GenerateSignature(Encoding.UTF8.GetBytes(message), privateKey);
            string signature = Convert.ToBase64String(signedBytes);
            return signature;
        }

        /// <summary>
        /// Verify ECDSA <paramref name="signature"/> of <paramref name="message"/> with given <paramref name="publicKey"/>.
        /// </summary>
        public static bool VerifySignature(byte[] message, byte[] signature, string publicKey)
        {
            if (message == null || message.Length == 0)
                throw new ArgumentException("message can't be null or zero length", nameof(message));

            AsymmetricKeyParameter keyParameter = GetAsymmetricKeyParameter(publicKey);
            ISigner sign = SignerUtilities.GetSigner("SHA256WithPlain-ECDSA");
            sign.Init(false, keyParameter);
            sign.BlockUpdate(message, 0, message.Length);
            bool isVerified = sign.VerifySignature(signature);
            return isVerified;
        }

        /// <summary>
        /// Verify ECDSA <paramref name="signature"/> of <paramref name="message"/> with given <paramref name="publicKey"/>.
        /// </summary>
        public static bool VerifySignature(string message, string signature, string publicKey)
        {
            bool isVerified = VerifySignature(Encoding.UTF8.GetBytes(message), Convert.FromBase64String(signature), publicKey);
            return isVerified;
        }
    }
}

Usage:

            var myKeys = ECDSAEncryption.GenerateRandomKeys();
            var mySignature = ECDSAEncryption.GenerateSignature("Hello World", myKeys.privateKey);
            var isVerified = ECDSAEncryption.VerifySignature("Hello World", mySignature, myKeys.publicKey);

If you need to talk more privately,
My email: [email protected]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants