2013-12-18 8 views
5

Ich versuche eine Zeichenfolge zu signieren und später mit dem öffentlichen Schlüssel zu verifizieren. Mein verifiziertes Ergebnis ist leer. Was mache ich falsch?Signieren und Decodieren mit RSA-SHA in GO

package main 

import (
    "crypto" 
    "crypto/rand" 
    "crypto/rsa" 
    "crypto/sha256" 
    "crypto/x509" 
    "encoding/base64" 
    "encoding/pem" 
    "errors" 
    "fmt" 
    "io/ioutil" 
) 

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("Encoded: %v\n", sig) 


    parser, perr := loadPublicKey("public.pem"); 
    if perr != nil { 
     fmt.Errorf("could not sign request: %v", err) 
    } 
    unsigned, err := parser.Unsign(signed); 
    if err != nil { 
     fmt.Errorf("could not sign request: %v", err) 
    } 

    fmt.Printf("Decrypted: %v\n", base64.StdEncoding.EncodeToString(unsigned))  
} 


// loadPrivateKey loads an parses a PEM encoded private key file. 
func loadPublicKey(path string) (Unsigner, error) { 
     data, err := ioutil.ReadFile(path) 

     if err != nil { 
       return nil, err 
     } 
     return parsePublicKey(data) 
} 

// 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) { 
     data, err := ioutil.ReadFile(path) 
     if err != nil { 
       return nil, err 
     } 
     return parsePrivateKey(data) 
} 

// 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) ([]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 encrypts data with rsa-sha256 
func (r *rsaPublicKey) Unsign(message []byte) ([]byte, error) { 
     return rsa.EncryptPKCS1v15(rand.Reader, r.PublicKey, message)   
} 

private.pem sieht wie folgt aus:

-----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----- 

Und public.pem:

-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3 
6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6 
Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw 
oYi+1hqp1fIekaxsyQIDAQAB 
-----END PUBLIC KEY----- 

Dank.

+0

Ich bin ein wenig verwirrt. Möchten Sie die Signatur codieren und dann dekodieren oder signieren und dann verifizieren? (Ich bin nicht allzu sehr mit Crypto-Terminologie vertraut) – ANisus

+0

Ich möchte die Signatur signieren und verifizieren. Aktualisierte Beschreibung –

+0

Seien Sie gewarnt, dass sich die RSA-Verschlüsselung/Entschlüsselung anders als die RSA-Signatur/Verifizierung mit einem Hash unterscheidet. Zumindest verwendet es einen anderen Auffüllmechanismus. –

Antwort

6

Das Problem in Ihrem Code ist, dass Unsign versucht, die Signatur zu verschlüsseln, anstatt es zu verwenden, um die ursprüngliche Nachricht zu überprüfen.

Es müssen Änderungen an der Oberfläche vorgenommen werden und zu Unsign:

// 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) 
} 

Hier ist ein Spielplatz Beispiel der Verifikation: http://play.golang.org/p/bzpD7Pa9mr

Einige Änderungen hat auch zu vermeiden IOUtils gemacht worden.

+0

Das Playgroud kann nicht ausgeführt werden. –

+0

@buzz: Hmm, ich habe gerade auf meinen Spielplatz geklickt und Run gedrückt. Es hat gut funktioniert. Versuchen Sie den Spielplatzcode lokal? – ANisus

+0

Oh, Entschuldigung, es ist meine Schuld. Ich habe einen Fehler gemacht. –