diff --git a/cryptobin/ssh/parse.go b/cryptobin/ssh/parse.go index 6ee506d..af4bc53 100644 --- a/cryptobin/ssh/parse.go +++ b/cryptobin/ssh/parse.go @@ -73,6 +73,31 @@ func (this SSH) ParseOpenSSHPrivateKeyFromPEMWithPassword(key []byte, password [ return privateKey, comment, info.CipherName, nil } +type openSSHPrivateKey struct { + CipherName string + KdfName string + KdfOpts string + NumKeys uint32 + PubKey []byte + PrivKeyBlock []byte +} + +// Parse OpenSSH PrivateKey To Info From PEM +func (this SSH) ParseOpenSSHPrivateKeyToInfoFromPEM(key []byte) (openSSHPrivateKey, error) { + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return openSSHPrivateKey{}, ErrKeyMustBePEMEncoded + } + + info, err := ssh.ParseOpenSSHPrivateKeyToInfo(block.Bytes) + if err != nil { + return openSSHPrivateKey{}, err + } + + return openSSHPrivateKey(info), nil +} + // Parse OpenSSH PublicKey From PEM func (this SSH) ParseOpenSSHPublicKeyFromPEM(key []byte) (crypto.PublicKey, string, error) { var err error diff --git a/cryptobin/ssh/ssh_test.go b/cryptobin/ssh/ssh_test.go index 07f78e6..daa3a6a 100644 --- a/cryptobin/ssh/ssh_test.go +++ b/cryptobin/ssh/ssh_test.go @@ -1,6 +1,7 @@ package ssh import ( + "fmt" "errors" "testing" "crypto/dsa" @@ -488,3 +489,107 @@ func Test_Error(t *testing.T) { err2 := tmp.Error().Error() assertEqual(err2, testerr.Error(), "Test_Error-Error") } + +var opensshprikey = ` +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdz +c2gtcnNhAAAAAwEAAQAAAQEAw9pq06KE3T2j+7Gxq7DM2WQ7gna5PNL2FLV1TcEJ +KSrxpg/uKhScLkwHV/pvL+etVm3WrO4T2lZZgGZySPU0MpQ9gTgjhPh3Iy0bgZ38 +0WelGCSAQ044XadTvRcsVMes/kJ2HG36RO9rbzinX+esFlgNN5BtjLAQDYV/KmPU +dqYQIT2wU7lIAh4g+G0n+w3wKpGuAQnhqDqca6bGjYQEJnzcLVMvOTd7K59EIOSQ +52C0fSiWLt5R542QxE+H0icNTwQS1gjfVStCMOsXdja86naIBdu6r+rXrKVHMjOf +/HFQ2rw9DQ1q12w5XWZMLUE07NCFek0kHmTLISzec3GjOQAAA8EMgLTuDIC07gAA +AAdzc2gtcnNhAAABAQDD2mrTooTdPaP7sbGrsMzZZDuCdrk80vYUtXVNwQkpKvGm +D+4qFJwuTAdX+m8v561Wbdas7hPaVlmAZnJI9TQylD2BOCOE+HcjLRuBnfzRZ6UY +JIBDTjhdp1O9FyxUx6z+QnYcbfpE72tvOKdf56wWWA03kG2MsBANhX8qY9R2phAh +PbBTuUgCHiD4bSf7DfAqka4BCeGoOpxrpsaNhAQmfNwtUy85N3srn0Qg5JDnYLR9 +KJYu3lHnjZDET4fSJw1PBBLWCN9VK0Iw6xd2NrzqdogF27qv6tespUcyM5/8cVDa +vD0NDWrXbDldZkwtQTTs0IV6TSQeZMshLN5zcaM5AAAAAwEAAQAAAQAtVaeYqWvb +0mLc5frcZSZlw7/KqTSjkamIjaBDiUVXlCsvZ0yXzQGB7fNdOAj4q8YB1Zb1nH5X +8djx0cTugmO8uXerK5V9OA5LxCszy6Az0Kv0dK6D5d1CQHMvt+d5EGdIy5WPax2d +S1Yw/oovtu6slWEp1XKmODLfDmGrLESH2eyICG0L1NPiexwA2qYi2Aj7HPXs7PgV +DClc8+CL6C+Yl0+y/5Uq/qi5Gg59t0+uSw1GFbkpQxQ+INzO8nS/NwXVIXE0VlQ3 +NimaI7dmsUaHGzi4LDjm2pEBBzdEQFb5TrN8YxjN8+TeayHdvVNgFUth+kZpsV7Q +RbKq2BpycczpAAAAgGW1gZb6ugVlqwGcRH0LK4+tBLY48ftGrOO6Wd7teKwHNq+V +xrLZvJ+vWY3Jww+TlkgaGHIGap/dUdXHMooskK69cmZEcobQfSqiBGcsmP9/0z6C +2lVsFNK6BfAAx2uOc0570rg+q36f4FgAnaueHkYXseJNzcVWJCYjXP9NQErKAAAA +gQDLREVn1etFyTyLHz5MZmLzfpGQu0PXSoIP8LiyNDKlwaTjUPkr6/CH0b9yEb+p +KtoqKfYKH7cH3VfjboEGN2WBpNfbeyXN1qr0vHClX+VOY4EBNb5Skprn99m5ytfn +g4SuwYvcVpl6xMcSOm75wGG8BA7X4N1ig7uZqLjw4SfVLwAAAIEA9qnJlmrwrPIO +INW6vPowAIAGLAYJdSdG1dXvXtcyMPxnPU1cipljX6C0QU5C9CExH9Jr1cEeFWbn +j9cVsSGYLuGR74DUrmAvwmWBItVWGj6z6v7gq7uldp14N3MK7yeXIQRSNbJKLJUx +e+do10dMBiKLMpylg0W8Nn2AoVpTRBcAAAAMdXNlckB3ZWIuY29t +-----END OPENSSH PRIVATE KEY----- +` + +var opensshpubkey = ` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD2mrTooTdPaP7sbGrsMzZZDuCdrk80vYUtXVNwQkpKvGmD+4qFJwuTAdX+m8v561Wbdas7hPaVlmAZnJI9TQylD2BOCOE+HcjLRuBnfzRZ6UYJIBDTjhdp1O9FyxUx6z+QnYcbfpE72tvOKdf56wWWA03kG2MsBANhX8qY9R2phAhPbBTuUgCHiD4bSf7DfAqka4BCeGoOpxrpsaNhAQmfNwtUy85N3srn0Qg5JDnYLR9KJYu3lHnjZDET4fSJw1PBBLWCN9VK0Iw6xd2NrzqdogF27qv6tespUcyM5/8cVDavD0NDWrXbDldZkwtQTTs0IV6TSQeZMshLN5zcaM5 user@web.com +` + +var opensshprikeyEn = ` +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAj +j6QR7gtMhCcL0hNVI7G1AAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAAB +AQDsUGub8db33AsanqRw4wmwFiu+J6aDp4RBpDR5nRDL7q/ssSSRLZwnyf8h4GXV +XxHFndRIqG+W30quQBxyQ7B67xNn858KwWzFFw+pgEfGHcDRwIhdZBFBFmwsBU06 +C7KcbV0f7tGuXTtJ8jfexjjWVy83lC6IiqxJZGHydPfNZXlBke4zpqCuJdJiSDhg +c/rBfV7In4MWwlSwY6hvWEFPs3SidSvDnqpKJ2ScgT8JRMQqtg9ifvz9tw5EWrTB +vqRWyPp8PUYqHN0fdAW+L8HFkIjmtgZKovbOWdy9iWdaHJ/guZLiLqDjM/PU3LSs +UZNiuUCU7AyA7xInEDmmRrv7AAAD0D/HlT0q8zNw5q89T4pB7wt5OemQrAa71EEL ++kKf9bWRRGX9ONcp2/RVE54BquKjHsp6PvXeR+9nOplYHCgJSGBUG61fQaPUe2qY +S8lGuQIABh7OT/yNcNyMiGczl9fXJ08OhJbd5FElr6AOTrksthRF2ocPyuEU9016 +CIdPD5v2o+L1PmG1t3LhEQMdwgXjHUSNBNmEUq5ZzFdvD2cDyLbZ6vSbxq0vCOrZ +uv9Br1SvPmPOeXsYpKJpWzq0fR7XrtB2XaDg2Ww/CcVDKD7Fjargy0Oa+NzDJw1W +2HmUbkjkvZS1tNQdXp+5RVtR4HkJKrI4subtQ2LwwX5opTpNs5jI+5Le/Jcsycj9 +K6zph/zi4uuLe3GpVu+rFNZDTVQTcgqGYf+0N9sGZnNPCMrAYMYQl7G/GLnGYBEz +TZERlV96b1wH4Nj25npIGRpbW/ftYw2MycbO+lNYmzi+c00L9Bdm2j2IkPm7jEt3 +ftCYXR2vq1oqUzERTfkBWB6f0HpBLmtX3nVTei/RiaJFhSQ5Wc1VAr+7veHoCRFW +3IuV4PyL9tY9mOJnrqV8NymICRdXbg2f0yDxXu9wp6tTJUSMHOy3WT8IZEoDlBJx +L8BK71CFLofxzFA33v+ds1gFZFitoxoYlJWG/n/wTZkwbN3JgvZymvXhJzjYV4Bs +nhL84UTuUMGXQoVcus0yxsP2F4IEui0+XT6nGd551B7NS3CRfQr59qGZbuOAVOHv +J4w/SEEpysnbCKloKn1mfcDPh3X6lQuI40BhD1R5XO/c8tBy5JTOlyyOS354Z/aG +PPFt+bFITSkYBrrs7p5lCDblhUDaMSqZ8BpLgYJhGFeWNAkCKAkFyfwkHdCWbLUA +AiW/arXuOULMLBGVyK9QojVzivUOBU7Zw3gwIKkxJfFFlRYv+9BIb19v22FbPbMQ +LZHmP2o+MQRUm3B7F1EdXiLvG+gZGYGBx2EDuRQ2B1W77NtAtD9iHNms/jNy1zlJ +lxd9TYYRNVsN+AE6VUotarnbN8P+KB8BecYfDi/Dnk2tAK9IbeAHDt/fIJcjQjAR +52uztU1i6xDv5CtKCDKVrHli+wVpBv/MMhDDBLV8ZeeHNlEwNktsPrdy6H+SURGv +A6mR+vu0XHPsnpHPnOAiWPh3JXvK1HguHeii4Z/Ey8YXfO2LZhYQBlaPgqEH3j1M +doyNN8XhiFgfrWxv+K5GWoDfDxZI322pWczQVDClwDOwR1OnUKE8wz2iFSK8oCtT +1XYy4Wp/UrxDyZB1crh4y5YlxUR54l4yxMZLw5wagZM/jQHABks= +-----END OPENSSH PRIVATE KEY----- +` + +var opensshpubkeyEn = ` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsUGub8db33AsanqRw4wmwFiu+J6aDp4RBpDR5nRDL7q/ssSSRLZwnyf8h4GXVXxHFndRIqG+W30quQBxyQ7B67xNn858KwWzFFw+pgEfGHcDRwIhdZBFBFmwsBU06C7KcbV0f7tGuXTtJ8jfexjjWVy83lC6IiqxJZGHydPfNZXlBke4zpqCuJdJiSDhgc/rBfV7In4MWwlSwY6hvWEFPs3SidSvDnqpKJ2ScgT8JRMQqtg9ifvz9tw5EWrTBvqRWyPp8PUYqHN0fdAW+L8HFkIjmtgZKovbOWdy9iWdaHJ/guZLiLqDjM/PU3LSsUZNiuUCU7AyA7xInEDmmRrv7 user@web.com +` + +func Test_ParseOpenSSHPrivateKeyToInfoFromPEM(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + assertError := cryptobin_test.AssertErrorT(t) + + newSSH := New() + + info, err := newSSH.ParseOpenSSHPrivateKeyToInfoFromPEM([]byte(opensshprikey)) + assertError(err, "ParseOpenSSHPrivateKeyToInfoFromPEM") + assertEqual(info.CipherName, "none", "CipherName") + assertEqual(info.KdfName, "none", "KdfName") + assertEqual(info.NumKeys, uint32(1), "NumKeys") +} + +func Test_ParseOpenSSHPrivateKeyToInfoFromPEM_And_En(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + assertError := cryptobin_test.AssertErrorT(t) + + newSSH := New() + + info, err := newSSH.ParseOpenSSHPrivateKeyToInfoFromPEM([]byte(opensshprikeyEn)) + assertError(err, "ParseOpenSSHPrivateKeyToInfoFromPEM") + assertEqual(info.CipherName, "aes256-cbc", "CipherName") + assertEqual(info.KdfName, "bcrypt", "KdfName") + assertEqual( + fmt.Sprintf("%x", info.KdfOpts), + "00000010238fa411ee0b4c84270bd2135523b1b500000010", + "KdfOpts", + ) + assertEqual(info.NumKeys, uint32(1), "NumKeys") +}