x/crypto/ssh: cannot sign certificate with different algorithm
stoggi opened this issue · 5 comments
What version of Go are you using (go version
)?
$ go version go version go1.13.4 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env not relevant
What did you do?
I want to be able to change the algorithm used when signing an SSH certificate. Specifically with a private key implemented in hardware with ssh.NewSignerFromSigner
.
What did you expect to see?
I should be able to pass an AlgorithmSigner
interface, and specify which algorithm to use when invoking Certificate.SignCert
What did you see instead?
When signing a certificate with Certificate.SignCert
I can not specify the algorithm used.
I am happy to contribute a change to fix this. I propose adding a new method to the Certificate
struct, named SignCertWithAlgorithm
which correctly calls authority.SignWithAlgorithm.
I've put together a short proof-of-concept implementing SignCertWithAlgorithm
and adding a new private method prepareForSigning
to keep the nonce generation in once place.
/cc @hanwen
An alternative implementation would be to create a NewAlgorithmSignerFromSigner
method to return a signer interface, that can sign with a particular algorithm. Then you could pass it to Certificate.SignCert
normally.
https://play.golang.org/p/lywpKtapMeZ
type sshAlgorithmSigner struct {
algorithm string
signer ssh.AlgorithmSigner
}
func (s *sshAlgorithmSigner) PublicKey() ssh.PublicKey {
return s.signer.PublicKey()
}
func (s *sshAlgorithmSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
return s.signer.SignWithAlgorithm(rand, data, s.algorithm)
}
func NewAlgorithmSignerFromSigner(signer crypto.Signer, algorithm string) (ssh.Signer, error) {
sshSigner, err := ssh.NewSignerFromSigner(signer)
if err != nil {
return nil, err
}
algorithmSigner, ok := sshSigner.(ssh.AlgorithmSigner)
if !ok {
return nil, errors.New("unable to cast to ssh.AlgorithmSigner")
}
s := sshAlgorithmSigner{
signer: algorithmSigner,
algorithm: algorithm,
}
return &s, nil
}
A particular urgency for this issue is that right now with an RSA private key, the default is SHA-1. OpenSSH 8.2 has removed support for RSA-SHA1 signatures on certificates: https://www.openssh.com/txt/release-8.2
Change https://go.dev/cl/508398 mentions this issue: ssh: add MultiAlgorithmSigner