Search code examples
vb.netssh-keysecdsachilkatchilkat-sshkey

"Incorrect" Password Loading Encrypted OpenSSH Key


I am trying to set up an application to use a Chilkat.SshKey to read my ECDSA 521-bit OpenSSH key for authentication to a new SSH server. I've read documentation and examples from the developers but I still get an error every time I try to load the key:

ChilkatLog:
  FromOpenSshPrivateKey(32ms):
    DllDate: May 25 2017
    ChilkatVersion: 9.5.0.68
    UnlockPrefix: <mycode>
    Architecture: Little Endian; 32-bit
    Language: .NET 4.5
    VerboseLogging: 1
    fromOpenSshPrivateKey(32ms):
      loadPem2(32ms):
        loadPem(16ms):
          itemType: OPENSSH PRIVATE KEY
          addPemItem(16ms):
            itemType: OPENSSH PRIVATE KEY
            loadAnyDerPw(16ms):
              DecodeToAsn:
                premature end of BER encoding (F2)
                length: 115
                numBytesLeft: 108
              --DecodeToAsn
              loadAnyAsn:
                Invalid ASN.1 for public/private key
              --loadAnyAsn
              der_to_xml:
                ASN data length exceeds remaining number of bytes available.
                tag: 19
                idClass: 1
                bConstructed: 1
                headerLen: 2
                dataLen: 115
                inlen: 108
                Abort ASN.1 processing...
                recursiveDepth: 2
                Abort ASN.1 processing...
                recursiveDepth: 1
              --der_to_xml
              der_xml: <?xml version="1.0" encoding="utf-8" ?>
<application tag="15" constructed="1">
    <application tag="5" constructed="1" />
</application>

            --loadAnyDerPw
          --addPemItem
          No more -----BEGIN's found.
        --loadPem
      --loadPem2
      Check the password, it may be incorrect.
    --fromOpenSshPrivateKey
    Failed.
  --FromOpenSshPrivateKey
--ChilkatLog

I've verified the password is correct by using ssh-keygen -y -f <path_to_private_key>. My code looks like this:

Dim MyKey As New SshKey With {.Password = "<private_key_password>", .VerboseLogging = True}
Dim SSHKeyString As String = MyKey.LoadText("<path_to_private_key>")

If Not MyKey.FromOpenSshPrivateKey(SSHKeyString) Then
    Throw New Exception("Failed to load the private key." & vbCrLf & vbCrLf & MyKey.LastErrorText)
Else
    MessageBox.Show("Private key loaded successfully")
End If

Initially, I had tried reading the file from a server share but, when I tried the ssh-keygen command, it was giving me an error:

Bad permissions. Try removing permissions for user: MYDOMAIN\\Domain Admins (sid) on file //SERVER/SSH/my-key-ecdsa.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for '\\\\SERVER\\SSH\\my-key-ecdsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "\\\\SERVER\\SSH\\my-key-ecdsa": bad permissions

I copied the file to a local drive and removed permissions for all but myself (my domain user) and was able to get the ssh-keygen command to correctly return the key information:

ecdsa-sha2-nistp521 <KEY CONTENTS HERE> [email protected]

Just to be sure, I also tested with a garbage password and it returned:

Load key "<path_to_private_key>": incorrect passphrase supplied to decrypt private key

What is it that I'm missing here?


Just to try to provide as much information as possible, here's an obfuscated/redacted version of the private key in question:

-----BEGIN OPENSSH PRIVATE KEY-----
[line 1]
[line 2]
[line 3]
[...]
-----END OPENSSH PRIVATE KEY-----

None of the example keys on the documentation page show this specific structure but, from the way the .LastErrorText reads, that doesn't appear to be the issue I'm facing.


Looking at Loading encrypted key, I started wondering if the issue may be that there's a punctuation character in the password I used to encrypt the key. Unfortunately, that doesn't appear to be the cause of the error.

I created a new key with the same parameters:

ssh-keygen -f "C:\temp_folder\test-key-ecdsa" -t ecdsa -b 521 -C [email protected]

I encrypted it with a simple password of testpass, but I'm still getting effectively the same .LastErrorText result with Check the password, it may be incorrect.

Next, I created a key with no password:

ssh-keygen -f "C:\temp_folder\nopass-key-ecdsa" -t ecdsa -b 521 -C [email protected]

This time, at least, I got a different error:

ChilkatLog:
  FromOpenSshPrivateKey(47ms):
    DllDate: May 25 2017
    ChilkatVersion: 9.5.0.68
    UnlockPrefix: <mycode>
    Architecture: Little Endian; 32-bit
    Language: .NET 4.5
    VerboseLogging: 1
    fromOpenSshPrivateKey(47ms):
      loadPem2(31ms):
        loadPem(31ms):
          itemType: OPENSSH PRIVATE KEY
          addPemItem(31ms):
            itemType: OPENSSH PRIVATE KEY
            loadAnyDerPw(16ms):
              DecodeToAsn:
                premature end of BER encoding (F2)
                length: 115
                numBytesLeft: 108
              --DecodeToAsn
              loadAnyAsn:
                Invalid ASN.1 for public/private key
              --loadAnyAsn
              der_to_xml:
                ASN data length exceeds remaining number of bytes available.
                tag: 19
                idClass: 1
                bConstructed: 1
                headerLen: 2
                dataLen: 115
                inlen: 108
                Abort ASN.1 processing...
                recursiveDepth: 2
                Abort ASN.1 processing...
                recursiveDepth: 1
              --der_to_xml
              der_xml: <?xml version="1.0" encoding="utf-8" ?>
<application tag="15" constructed="1">
    <application tag="5" constructed="1" />
</application>

            --loadAnyDerPw
          --addPemItem
          No more -----BEGIN's found.
        --loadPem
      --loadPem2
      Did you forget to set the Password property on this SshKey object prior to loading this private key?
    --fromOpenSshPrivateKey
    Failed.
  --FromOpenSshPrivateKey
--ChilkatLog

I tried both by removing the .Password property of the Chilkat.SshKey object constructor, as well as by explicitly setting it to String.Empty and Nothing, but get the same results each time.


Solution

  • Apparently, this issue was caused by an outdated version of the library and has since been resolved. As the .LastErrorText showed, I was using v9.5.0.68 from May 25, 2017. I've been using this library in my application for quite a while, but I've never had a need to use SSH keys for authentication before.

    On a lark, I created a new console application (.NET 6.0) and installed the latest ChilkatDnCore library (v9.50.95) from NuGet. I then tested all three of the keys with the following code:

    Sub Main(args As String())
        Dim SSHComm As New Chilkat.SFtp
        Dim LibraryUnlocked As Boolean = CheckSSHComponent(SSHComm)
        Dim SSHKeyString As String
        Dim NoPassKey As New SshKey With {.VerboseLogging = True}
    
        SSHKeyString = NoPassKey.LoadText("C:\temp_folder\nopass-key-ecdsa")
    
        If Not NoPassKey.FromOpenSshPrivateKey(SSHKeyString) Then
            Console.WriteLine("Failed to load the private key: nopass-key-ecdsa")
            Console.WriteLine(NoPassKey.LastErrorText)
        Else
            Console.WriteLine("Private key loaded successfully: nopass-key-ecdsa")
            Console.WriteLine(NoPassKey.KeyType)
        End If
    
        Dim TestKey As New SshKey With {.VerboseLogging = True, .Password = "testpass"}
    
        SSHKeyString = TestKey.LoadText("C:\temp_folder\test-key-ecdsa")
    
        If Not TestKey.FromOpenSshPrivateKey(SSHKeyString) Then
            Console.WriteLine("Failed to load the private key: test-key-ecdsa")
            Console.WriteLine(TestKey.LastErrorText)
        Else
            Console.WriteLine("Private key loaded successfully: test-key-ecdsa")
            Console.WriteLine(TestKey.KeyType)
        End If
    
        Dim LiveKey As New SshKey With {.VerboseLogging = True, .Password = <live_key_password>}
    
        SSHKeyString = LiveKey.LoadText("C:\temp_folder\live-key-ecdsa")
    
        If Not LiveKey.FromOpenSshPrivateKey(SSHKeyString) Then
            Console.WriteLine("Failed to load the private key: live-key-ecdsa")
            Console.WriteLine(LiveKey.LastErrorText)
        Else
            Console.WriteLine("Private key loaded successfully: live-key-ecdsa")
            Console.WriteLine(LiveKey.KeyType)
        End If
    End Sub
    

    The results were all successful:

    Private key loaded successfully: nopass-key-ecdsa
    ecdsa
    Private key loaded successfully: test-key-ecdsa
    ecdsa
    Private key loaded successfully: live-key-ecdsa
    ecdsa
    

    So, I went back to my original application and removed the old, direct file reference to the Chilkat library I had and downloaded the latest version from NuGet with the Package Manager. Testing there was successful as well.

    Finally, just to try to implement my original intent, I changed the path of the private key file back to the network share and tested one last time. Once again, everything was successful.

    I admit that I've been avoiding upgrading the library for a while for fear of having to recode stuff, but I'm not seeing any other errors, so I guess that's all I needed.