1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
| package main
import ("crypto" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/pem" "errors" "fmt" )
func main() {signer, err := loadPrivateKey("private.pem") if err != nil {fmt.Errorf("signer is damaged: %v", err) }
toSign := "date: Thu, 05 Jan 2012 21:31:40 GMT"
signed, err := signer.Sign([]byte(toSign)) if err != nil {fmt.Errorf("could not sign request: %v", err) } sig := base64.StdEncoding.EncodeToString(signed) fmt.Printf("Signature: %v\n", sig)
parser, perr := loadPublicKey("public.pem") if perr != nil {fmt.Errorf("could not sign request: %v", err) }
err = parser.Unsign([]byte(toSign), signed) if err != nil {fmt.Errorf("could not sign request: %v", err) }
fmt.Printf("Unsign error: %v\n", err) }
// loadPrivateKey loads an parses a PEM encoded private key file. func loadPublicKey(path string) (Unsigner, error) {return parsePublicKey([]byte(`-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3 6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6 Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw oYi+1hqp1fIekaxsyQIDAQAB -----END PUBLIC KEY-----`)) }
// parsePublicKey parses a PEM encoded private key. func parsePublicKey(pemBytes []byte) (Unsigner, error) {block, _ := pem.Decode(pemBytes) if block == nil {return nil, errors.New("ssh: no key found")}
var rawkey interface{} switch block.Type {case"PUBLIC KEY": rsa, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil {return nil, err} rawkey = rsa default: return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) }
return newUnsignerFromKey(rawkey) }
// loadPrivateKey loads an parses a PEM encoded private key file. func loadPrivateKey(path string) (Signer, error) {return parsePrivateKey([]byte(`-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u 412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7 kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI 7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA== -----END RSA PRIVATE KEY-----`)) }
// parsePublicKey parses a PEM encoded private key. func parsePrivateKey(pemBytes []byte) (Signer, error) {block, _ := pem.Decode(pemBytes) if block == nil {return nil, errors.New("ssh: no key found")}
var rawkey interface{} switch block.Type {case"RSA PRIVATE KEY": rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil {return nil, err} rawkey = rsa default: return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) } return newSignerFromKey(rawkey) }
// A Signer is can create signatures that verify against a public key. type Signer interface { // Sign returns raw signature for the given data. This method // will apply the hash specified for the keytype to the data. Sign(data []byte) ([]byte, error) }
// A Signer is can create signatures that verify against a public key. type Unsigner interface { // Sign returns raw signature for the given data. This method // will apply the hash specified for the keytype to the data. Unsign(data[]byte, sig []byte) error }
func newSignerFromKey(k interface{}) (Signer, error) { var sshKey Signer switch t := k.(type) { case *rsa.PrivateKey: sshKey = &rsaPrivateKey{t} default: return nil, fmt.Errorf("ssh: unsupported key type %T", k) } return sshKey, nil }
func newUnsignerFromKey(k interface{}) (Unsigner, error) { var sshKey Unsigner switch t := k.(type) { case *rsa.PublicKey: sshKey = &rsaPublicKey{t} default: return nil, fmt.Errorf("ssh: unsupported key type %T", k) } return sshKey, nil }
type rsaPublicKey struct {*rsa.PublicKey}
type rsaPrivateKey struct {*rsa.PrivateKey}
// Sign signs data with rsa-sha256 func (r *rsaPrivateKey) Sign(data []byte) ([]byte, error) {h := sha256.New() h.Write(data) d := h.Sum(nil) return rsa.SignPKCS1v15(rand.Reader, r.PrivateKey, crypto.SHA256, d) }
// Unsign verifies the message using a rsa-sha256 signature func (r *rsaPublicKey) Unsign(message []byte, sig []byte) error {h := sha256.New() h.Write(message) d := h.Sum(nil) return rsa.VerifyPKCS1v15(r.PublicKey, crypto.SHA256, d, sig) }
|