@@ -68,9 +68,8 @@ var hashToDef = map[crypto.Hash]struct {
6868 // http://www.iana.org/assignments/signature-algorithms
6969 //
7070 // Note that the forbidden hashes have an invalid 'new' function.
71- crypto .MD4 : {md4String , func (key []byte ) (hash.Hash , error ) { return nil , nil }},
72- crypto .MD5 : {md5String , func (key []byte ) (hash.Hash , error ) { return nil , nil }},
73- // Temporarily enable SHA1 because of issue https://github.com/golang/go/issues/37278
71+ crypto .MD4 : {md4String , func (key []byte ) (hash.Hash , error ) { return nil , nil }},
72+ crypto .MD5 : {md5String , func (key []byte ) (hash.Hash , error ) { return nil , nil }},
7473 crypto .SHA1 : {sha1String , func (key []byte ) (hash.Hash , error ) { return sha1 .New (), nil }},
7574 crypto .SHA224 : {sha224String , func (key []byte ) (hash.Hash , error ) { return sha256 .New224 (), nil }},
7675 crypto .SHA256 : {sha256String , func (key []byte ) (hash.Hash , error ) { return sha256 .New (), nil }},
@@ -192,11 +191,49 @@ func (r *rsaAlgorithm) setSig(b []byte) error {
192191 return nil
193192}
194193
194+ // Code from https://github.com/cloudtools/ssh-cert-authority/pull/49/files
195+ // This interface provides a way to reach the exported, but not accessible SignWithOpts() method
196+ // in x/crypto/ssh/agent. Access to this is needed to sign with more secure signing algorithms
197+ type agentKeyringSigner interface {
198+ SignWithOpts (rand io.Reader , data []byte , opts crypto.SignerOpts ) (* ssh.Signature , error )
199+ }
200+
201+ // A struct to wrap an SSH Signer with one that will switch to SHA256 Signatures.
202+ // Replaces the call to Sign() with a call to SignWithOpts using HashFunc() algorithm.
203+ type Sha256Signer struct {
204+ ssh.Signer
205+ }
206+
207+ func (s Sha256Signer ) HashFunc () crypto.Hash {
208+ return crypto .SHA256
209+ }
210+
211+ func (s Sha256Signer ) Sign (rand io.Reader , data []byte ) (* ssh.Signature , error ) {
212+ if aks , ok := s .Signer .(agentKeyringSigner ); ! ok {
213+ return nil , fmt .Errorf ("ssh: can't wrap a non ssh agentKeyringSigner" )
214+ } else {
215+ return aks .SignWithOpts (rand , data , s )
216+ }
217+ }
218+
195219func (r * rsaAlgorithm ) Sign (rand io.Reader , p crypto.PrivateKey , sig []byte ) ([]byte , error ) {
196220 if r .sshSigner != nil {
197- sshsig , err := r .sshSigner .Sign (rand , sig )
198- if err != nil {
199- return nil , err
221+ var (
222+ sshsig * ssh.Signature
223+ err error
224+ )
225+ // are we using an SSH Agent
226+ if _ , ok := r .sshSigner .(agentKeyringSigner ); ok {
227+ signer := Sha256Signer {r .sshSigner }
228+ sshsig , err = signer .Sign (rand , sig )
229+ if err != nil {
230+ return nil , err
231+ }
232+ } else {
233+ sshsig , err = r .sshSigner .(ssh.AlgorithmSigner ).SignWithAlgorithm (rand , sig , ssh .SigAlgoRSASHA2256 )
234+ if err != nil {
235+ return nil , err
236+ }
200237 }
201238
202239 return sshsig .Blob , nil
0 commit comments