[GH-ISSUE #120] Support private key files from OpenSSL #96

Closed
opened 2026-02-26 10:35:53 +03:00 by kerem · 13 comments
Owner

Originally created by @matbech on GitHub (Jan 3, 2016).
Original GitHub issue: https://github.com/Pro/dkim-exchange/issues/120

Currently it seems that DKIM agent fails to read private key files (.pem) which contain line breaks at position 65. When creating private keys with openssl, it creates .pem with line breaks at position 65:
openssl genrsa -out private.pem
I believe the DKIM signer should support .pem key files with line breaks.

Originally created by @matbech on GitHub (Jan 3, 2016). Original GitHub issue: https://github.com/Pro/dkim-exchange/issues/120 Currently it seems that DKIM agent fails to read private key files (.pem) which contain line breaks at position 65. When creating private keys with openssl, it creates .pem with line breaks at position 65: openssl genrsa -out private.pem I believe the DKIM signer should support .pem key files with line breaks.
kerem 2026-02-26 10:35:53 +03:00
  • closed this issue
  • added the
    gui
    agent
    labels
Author
Owner

@Pro commented on GitHub (Jan 3, 2016):

I tested with a key from openssl genrsa -out private.pem and it works for me now.

<!-- gh-comment-id:168499243 --> @Pro commented on GitHub (Jan 3, 2016): I tested with a key from `openssl genrsa -out private.pem` and it works for me now.
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

Thank you. I get the following error now with my key:

Couldn't load private key for domain abcd.com from C:\Program Files\Exchange DkimSigner\keys\abcd.com.pem: Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters' to type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair'.

I think the AsymmetricKeyParameters you used before was correct:
github.com/Pro/dkim-exchange@d8fa12dee2 (diff-80fbe89954)

<!-- gh-comment-id:168499799 --> @matbech commented on GitHub (Jan 3, 2016): Thank you. I get the following error now with my key: Couldn't load private key for domain abcd.com from C:\Program Files\Exchange DkimSigner\keys\abcd.com.pem: Unable to cast object of type 'Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters' to type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair'. I think the AsymmetricKeyParameters you used before was correct: https://github.com/Pro/dkim-exchange/commit/d8fa12dee2dc77636ba48ed6e035de803a9b1892#diff-80fbe899548913d9af44190d7c253f97L969
Author
Owner

@Pro commented on GitHub (Jan 3, 2016):

Unfortunately, the MimeKit DKIM signer expects the key to be of type AsymmetricCipherKeyPair thus I had it to change from AsymmetricKeyParameters.

If the key is of type AsymmetricKeyParameters it means that it is in the PKCS#8 format (and does only contain the private key, not the public key).

Which command did you use to generate your key? Because openssl genrsa -out private.pem generates a key pair.

<!-- gh-comment-id:168500102 --> @Pro commented on GitHub (Jan 3, 2016): Unfortunately, the MimeKit DKIM signer expects the key to be of type `AsymmetricCipherKeyPair` thus I had it to change from `AsymmetricKeyParameters`. If the key is of type `AsymmetricKeyParameters` it means that it is in the PKCS#8 format (and does only contain the private key, not the public key). Which command did you use to generate your key? Because `openssl genrsa -out private.pem` generates a key pair.
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

I have extracted the private key from PKCS12 .pfx using this command:
openssl pkcs12 -in abcd.com.pfx -nocerts -out abcd.com.pem -nodes

<!-- gh-comment-id:168500516 --> @matbech commented on GitHub (Jan 3, 2016): I have extracted the private key from PKCS12 .pfx using this command: openssl pkcs12 -in abcd.com.pfx -nocerts -out abcd.com.pem -nodes
Author
Owner

@Pro commented on GitHub (Jan 3, 2016):

What happens, if you take the PKCS12 abcd.com.pfx instead of the extracted key? Just to see what happens...

<!-- gh-comment-id:168500818 --> @Pro commented on GitHub (Jan 3, 2016): What happens, if you take the PKCS12 `abcd.com.pfx` instead of the extracted key? Just to see what happens...
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

I removed the password from the .pfx and verified the output. Then tried to select it in the configurator:
"The selected key is not a valid private key"

<!-- gh-comment-id:168501125 --> @matbech commented on GitHub (Jan 3, 2016): I removed the password from the .pfx and verified the output. Then tried to select it in the configurator: "The selected key is not a valid private key"
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

Maybe if you get a RSAPrivateCrtKeyParameters object you could build a AsymmetricCipherKeyPair as following:

RSAPrivateCrtKeyParameters rsaParameters;
var publicParameters = new RSAKeyParameters(rsaParameters.getModulus(), rsaParameters.getExponent());
var pair = new AsymmetricCipherKeyPair(rsaParameters, publicParameters);
// or new AsymmetricCipherKeyPair(rsaParameters, rsaParameters);?
<!-- gh-comment-id:168501784 --> @matbech commented on GitHub (Jan 3, 2016): Maybe if you get a RSAPrivateCrtKeyParameters object you could build a AsymmetricCipherKeyPair as following: ``` RSAPrivateCrtKeyParameters rsaParameters; var publicParameters = new RSAKeyParameters(rsaParameters.getModulus(), rsaParameters.getExponent()); var pair = new AsymmetricCipherKeyPair(rsaParameters, publicParameters); // or new AsymmetricCipherKeyPair(rsaParameters, rsaParameters);? ```
Author
Owner

@Pro commented on GitHub (Jan 3, 2016):

And another try. The configurator and signer now supports default RSA private keys and the ones exported from PKCS12 files.

@matbech please try the newly compiled .dll (and configurator) in https://github.com/Pro/dkim-exchange/tree/master/Src/Exchange.DkimSigner/bin

<!-- gh-comment-id:168517661 --> @Pro commented on GitHub (Jan 3, 2016): And another try. The configurator and signer now supports default RSA private keys and the ones exported from PKCS12 files. @matbech please try the newly compiled .dll (and configurator) in https://github.com/Pro/dkim-exchange/tree/master/Src/Exchange.DkimSigner/bin
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

The configurator is able to load the private key now. However I get this message from the agent:
"Could not initialize MimeKit DkimSigner for domain abcd.com: Private key not found."

Looking at the MimeKit source:

public DkimSigner(string fileName, string domain, string selector)
...
    using (FileStream stream = File.OpenRead(fileName))
    {
        using (StreamReader reader = new StreamReader(stream))
        {
            PemReader reader2 = new PemReader(reader);
            pair = reader2.ReadObject() as AsymmetricCipherKeyPair;
        }
    }
    if (pair == null)
    {
        throw new FormatException("Private key not found.");
    }

It tells me that you cannot use this constructor because it always expects a AsymmetricCipherKeyPair. Instead read the private key into an AsymmetricKeyParameter object, and use the DkimSigner ctor which takes the AsymmetricKeyParameter argument.

public DkimSigner(AsymmetricKeyParameter key, string domain, string selector)

Please also note the extra whitespace in front of the domain name in the error message. PR: https://github.com/Pro/dkim-exchange/pull/124

<!-- gh-comment-id:168518500 --> @matbech commented on GitHub (Jan 3, 2016): The configurator is able to load the private key now. However I get this message from the agent: "Could not initialize MimeKit DkimSigner for domain abcd.com: Private key not found." Looking at the MimeKit source: ``` public DkimSigner(string fileName, string domain, string selector) ... using (FileStream stream = File.OpenRead(fileName)) { using (StreamReader reader = new StreamReader(stream)) { PemReader reader2 = new PemReader(reader); pair = reader2.ReadObject() as AsymmetricCipherKeyPair; } } if (pair == null) { throw new FormatException("Private key not found."); } ``` It tells me that you cannot use this constructor because it always expects a AsymmetricCipherKeyPair. Instead read the private key into an AsymmetricKeyParameter object, and use the DkimSigner ctor which takes the AsymmetricKeyParameter argument. ``` public DkimSigner(AsymmetricKeyParameter key, string domain, string selector) ``` Please also note the extra whitespace in front of the domain name in the error message. PR: https://github.com/Pro/dkim-exchange/pull/124
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

In an earlier comment you mentioned that the DKIM signer requires a AsymmetricCipherKeyPair. However when I look at the documentation it says it expects a AsymmetricKeyParameter:
http://www.mimekit.net/docs/html/M_MimeKit_Cryptography_DkimSigner__ctor.htm

So I would rewrite the KeyHelper.ParseKeyPair
https://github.com/Pro/dkim-exchange/blob/master/Src/Exchange.DkimSigner/Helper/KeyHelper.cs#L19

 public static AsymmetricKeyParameter ParseKeyPair(string privateKeyFile)
        {
            object obj = ReadPem(privateKeyFile);
            if (obj == null)
                throw new FormatException("The key file has an invalid PEM format. " + privateKeyFile);

            if (obj is AsymmetricKeyParameter)
            {
                return obj as AsymmetricKeyParameter;
            }
            if (obj is AsymmetricCipherKeyPair)
            {
                var pair = obj as AsymmetricCipherKeyPair;
                return pair.Private;
            }

            throw new FormatException("The given key does not have the correct type. The keyfile must include the private and public key in PEM format. It is of type: " +
                                      obj.GetType());

        }

and something similar in the agent.

<!-- gh-comment-id:168521437 --> @matbech commented on GitHub (Jan 3, 2016): In an earlier comment you mentioned that the DKIM signer requires a AsymmetricCipherKeyPair. However when I look at the documentation it says it expects a AsymmetricKeyParameter: http://www.mimekit.net/docs/html/M_MimeKit_Cryptography_DkimSigner__ctor.htm So I would rewrite the KeyHelper.ParseKeyPair https://github.com/Pro/dkim-exchange/blob/master/Src/Exchange.DkimSigner/Helper/KeyHelper.cs#L19 ``` public static AsymmetricKeyParameter ParseKeyPair(string privateKeyFile) { object obj = ReadPem(privateKeyFile); if (obj == null) throw new FormatException("The key file has an invalid PEM format. " + privateKeyFile); if (obj is AsymmetricKeyParameter) { return obj as AsymmetricKeyParameter; } if (obj is AsymmetricCipherKeyPair) { var pair = obj as AsymmetricCipherKeyPair; return pair.Private; } throw new FormatException("The given key does not have the correct type. The keyfile must include the private and public key in PEM format. It is of type: " + obj.GetType()); } ``` and something similar in the agent.
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

MimeKit just merged a related patch I have submitted:
https://github.com/jstedfast/MimeKit/pull/216

It should simplify the required changes now.

<!-- gh-comment-id:168526909 --> @matbech commented on GitHub (Jan 3, 2016): MimeKit just merged a related patch I have submitted: https://github.com/jstedfast/MimeKit/pull/216 It should simplify the required changes now.
Author
Owner

@Pro commented on GitHub (Jan 3, 2016):

@matbech thanks again! Totally missed that constructor. Recompiled sources are in the repo. Lets see if this fixes it

<!-- gh-comment-id:168527163 --> @Pro commented on GitHub (Jan 3, 2016): @matbech thanks again! Totally missed that constructor. Recompiled sources are in the repo. Lets see if this fixes it
Author
Owner

@matbech commented on GitHub (Jan 3, 2016):

Thank you. It is working now :-)

<!-- gh-comment-id:168527503 --> @matbech commented on GitHub (Jan 3, 2016): Thank you. It is working now :-)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/dkim-exchange-Pro#96
No description provided.