2013-12-18 10 views
5

文字列に署名しようとしており、後で公開鍵で検証しようとしています。私の検証結果は空です。私は間違って何をしていますか?GOでRSA-SHAを使用した署名と復号

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は次のようになります。

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

そしてpublic.pem:

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

感謝。

+0

少し混乱しています。エンコードしてデコードするか、署名してから署名を検証しますか? (私は暗号の用語であまりにも使われているわけではない) – ANisus

+0

私は署名に署名したいと思う。更新された説明。 –

+0

一般的な考え方とは異なり、RSAの暗号化/復号化はRSAの署名/検証とはハッシュで異なる点に注意してください。少なくとも、異なるパディングメカニズムを使用します。 –

答えて

6

コードの問題点は、Unsignは、元のメッセージを確認する代わりにUnsignが署名をエンコードしようとしていることです。

そこには、インターフェイスにして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) 
} 

ここでは、検証の遊び場の例である:http://play.golang.org/p/bzpD7Pa9mr

いくつかの変更もioutilsを避けるために行われています。

+0

playgroudは実行できません。 –

+0

@buzz:ちょっと、私の遊び場のリンクをクリックし、Runを押しました。それは正常に働いた。あなたは遊び場のコードをローカルで試していますか? – ANisus

+0

ああ、申し訳ありませんが、それは私のせいです。私は間違いをする。 –

関連する問題