Created
August 8, 2017 08:36
-
-
Save ZhenhangTung/0d96e73f1c89a77f4d70adb032420609 to your computer and use it in GitHub Desktop.
The code is in this question(https://stackoverflow.com/q/20655702/3970355). It's about how to load rsa key and do the sign and unsign.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment