diff --git a/ssh/keys.go b/ssh/keys.go index a035956fcc..47a07539d9 100644 --- a/ssh/keys.go +++ b/ssh/keys.go @@ -1490,6 +1490,7 @@ type openSSHEncryptedPrivateKey struct { NumKeys uint32 PubKey []byte PrivKeyBlock []byte + Rest []byte `ssh:"rest"` } type openSSHPrivateKey struct { diff --git a/ssh/keys_test.go b/ssh/keys_test.go index 661e3cb31c..a1165ec68b 100644 --- a/ssh/keys_test.go +++ b/ssh/keys_test.go @@ -271,6 +271,21 @@ func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) { } } +func TestParseEncryptedPrivateKeysWithUnsupportedCiphers(t *testing.T) { + for _, tt := range testdata.UnsupportedCipherData { + t.Run(tt.Name, func(t *testing.T){ + _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) + if err == nil { + t.Fatalf("expected 'unknown cipher' error for %q, got nil", tt.Name) + // If this cipher is now supported, remove it from testdata.UnsupportedCipherData + } + if !strings.Contains(err.Error(), "unknown cipher") { + t.Errorf("wanted 'unknown cipher' error, got %v", err.Error()) + } + }) + } +} + func TestParseEncryptedPrivateKeysWithIncorrectPassphrase(t *testing.T) { pem := testdata.PEMEncryptedKeys[0].PEMBytes for i := 0; i < 4096; i++ { diff --git a/ssh/testdata/keys.go b/ssh/testdata/keys.go index 6e48841b67..adb4244eb3 100644 --- a/ssh/testdata/keys.go +++ b/ssh/testdata/keys.go @@ -310,6 +310,53 @@ gbDGyT3bXMQtagvCwoW+/oMTKXiZP5jCJpEO8= }, } +var UnsupportedCipherData = []struct { + Name string + EncryptionKey string + PEMBytes []byte +} { + 0: { + Name: "ed25519-encrypted-chacha20-poly1305", + EncryptionKey: "password", + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAAHWNoYWNoYTIwLXBvbHkxMzA1QG9wZW5zc2guY29tAAAABm +JjcnlwdAAAABgAAAAQdPyPIjXDRAVHskY0yp9SWwAAAGQAAAABAAAAMwAAAAtzc2gtZWQy +NTUxOQAAACBi6qXITEUrmNce/c2lfozxALlKH3o/6sll8G7wzl1lvQAAAJDNlW1sEkvnK0 +8EecF1vHdPk85yClbh3KkHv09mbGAX/Gk6cJpYEGgJSkO7OEF4kG9DVGGd17+TZbTnM4LD +vYAJZExx2XLgJFEtHCVmJjYzwxx7yC7+s6u/XjrSlZS60RHunOPKyq+C+s48sejXvmX+t5 +0ZoVCI8aftT0ycis3gvLU9sCwJ2UnF6kAV226Z4g2aLkuJbgCDTEcYCRD64K1r +-----END OPENSSH PRIVATE KEY----- +`), + }, + 1: { + Name: "ed25519-encrypted-aes128-gcm", + EncryptionKey: "password", + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA +AAGAAAABBeMJIOqiyFwNCvDv6f8tQeAAAAZAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAA +IGYpUcb3tGp9kF6pppcUdq3EPMr85BaSUdhiXGbhS5YNAAAAkNBtMEu0UlLgToThuQc+4m +/o0DfFIERu0sspQivn5RJHCtulVKfU9BMiEnF0+LOMOABMlYesgLOtoMxwm4ZCSWH54kZk +vaFyyvvxY+RLDuWNQZCryffIA4+iLCUQR1EdxMDiJweKnGJuD64a+9xTJt47A3Vq4SYzji +EuVmM0FqS8lbT2ynYSe3va0Qyw13jEO5qbtCuyG+C5GejL7kX4Z64= +-----END OPENSSH PRIVATE KEY----- +`), + }, + 2: { + Name: "ed25519-encrypted-aes256-gcm", + EncryptionKey: "password", + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAAFmFlczI1Ni1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA +AAGAAAABBR1p3vH2Wr/HPL+q20L2rjAAAAZAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAA +IM3tT1xrAuOHcrBdoLRo/ojWZsAw2lHfF5hJgFEOts5MAAAAkH/YGrDhDw8u+F8e4P+84B +tAzvp55Lf1Yl7y34BrVmqlWqw/7boqahOp6iYJHNpcuanzc5T6s7Z3wSSYodbY1uvFOfbj +rtP6rIHQIY5J2C40WOYJN8IkZlkwDXwZY0qoE9699ZYmWdwsXRZ7QDhjd2W8ziyZBsttiB +kv2ceuJMLT04TrKc2+RUkj4CQYnz7p8EkgZlUozx8wBSxKFGnkP7k= +-----END OPENSSH PRIVATE KEY----- +`), + }, +} + + // SKData contains a list of PubKeys backed by U2F/FIDO2 Security Keys and their test data. var SKData = []struct { Name string