简体   繁体   English

javascript / golang RSA加密/验证

[英]javascript / golang RSA encrypt / verify

I have the following javascript on the client 我在客户端上有以下javascript

var NodeRSA = require('node-rsa');

var ClientSide = new NodeRSA({ b: 512 });
var privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAj1IEeouqDYiMX0rMiPAI64UntzNxE01+tB+k+aKesHzVXE5A
GnyWHIFdrByfjR93CMh3y56xsL78VP1/Xp8iVmAnbiFN5kpmawJ1owhDvNIl8A+Q
UiDzMg0z/yepzjp61Dg4CUFzGrmTfYO1aMWyWhR0ZKfy+HvVaGjpod2ioScU7Fkz
eO+fDR85quLFta7OXDwqD4NCPYeZTS5fgK1Nn72nrItoj5e36fzWvZntfvi4NHt7
nqOj4VH5e5YJHvmLWHh5Swh+OVyIAwhxYSK5PSupicGG8ixVy75hkjzZ2vW5JdVW
MPYbVUMpqjtE+i1zQTYNJ36hM/zznZR/drU7UwIDAQABAoIBAHvs02qTMWuaUqZj
KxCNXWkpLfo/RNsH+zMM2b3xW34HswWps8wzRilHwxN7fIquVmMF1HAAvGyz98QV
nfjXaP1/DxkvOwiR9JU6/zUFhGzU2XEGRCh/zUnOGNPcG/vynRq7sdhu+3R0WpAB
Pu9lYp55aVtPzcwGZ7VsYfhQiLsGnJ5GkBS7z4P3aG29By6fGnTwR83iQHtR5SvQ
Rb/xJxZjTM00OZ2ssAtw24Hu8QXTuOAHdy2B5E1tsF+hVHs4iB0OiLzW7m4GBkb/
/og76ouB4G+j6IjG2E5TO0eAdslKn2w3dZRgqnVDF5CPtRdbAc83xOwSouuuqN26
FPsLkwECgYEA4Jyf3j9UzW0znnOcul4MDvfKuMCzD/5wnc24aYBbie4Joi/jqDbc
9J5jqyfgzdqwjxiwkEFJi7gBcclO1i1SoIfA6ooVoJeQlzdMpSytZVhzgE2aJO1E
ORP7kLimAHysjMJ27Fix1VRZltcZe0E9DErkw/hoPemAMvDvW2myyaECgYEAo1k7
iS4O9GSHUKvbEJWR5r+9Qvv4aObOaRFRDfq4/E9fZwujzKAvxwkGFXjxwpzxKJqN
paVEL2cWY+S46f4B501xgnNknuf6po8ZEaXD5vy281xoU4YX1KFySbV8eXGmkyiO
M2+vPGrsTGOIsKnQW8jmaxWTClbSdPoLWfwzqHMCgYAS/Kp2+xuMEgMfDd7d0j1q
tn+ohoGchIG4lT9Vi8gxLLIbx7iS67BZ7Vm3ijNys13hetDSIPK6oN9eYwoLCOHH
ODKSoQGbBbTvU3ljLRerTYLWAblaDcSKnqnRXgqKV/+uFnI/IHBH/E1mduBsjuM+
OsaD2mfVc/umUr+pFpJKgQKBgCeaTb3fhc6oxMnBMLZfnOT13Zvs3PgJ5UdB5IXg
IJNDZxzjjI3i1FKMFIaGMQ7+39T5S5g6bkKT2rDTViWc6Lc8ZmW7Nkz0byeMkAZg
SxOod26fG8gMPaDWl4/ZSVlkPX92GKvNyw152tpWU2CJezOVjI+vxlt+Wz3zFWd2
psuTAoGAbdlzYFK+7e2ru8fdbVk9SBLn9cnPdDCx+wgJV7dB0zzSh1oqIrE766Mx
c9wBIKWNqNEsFsFI4ejuMRdC4Hyc6ecCNea3nj3BHCS70V0p1MtFII6SpADDqBTW
3ZnLfcN2MiFDBXVqNkCsMcqd8KVdzEqEy1JDplmW84OpfQu88ms=
-----END RSA PRIVATE KEY-----`
var publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj1IEeouqDYiMX0rMiPAI
64UntzNxE01+tB+k+aKesHzVXE5AGnyWHIFdrByfjR93CMh3y56xsL78VP1/Xp8i
VmAnbiFN5kpmawJ1owhDvNIl8A+QUiDzMg0z/yepzjp61Dg4CUFzGrmTfYO1aMWy
WhR0ZKfy+HvVaGjpod2ioScU7FkzeO+fDR85quLFta7OXDwqD4NCPYeZTS5fgK1N
n72nrItoj5e36fzWvZntfvi4NHt7nqOj4VH5e5YJHvmLWHh5Swh+OVyIAwhxYSK5
PSupicGG8ixVy75hkjzZ2vW5JdVWMPYbVUMpqjtE+i1zQTYNJ36hM/zznZR/drU7
UwIDAQAB
-----END PUBLIC KEY-----`

ClientSide.importKey(privateKey, 'pkcs1');
let result = ClientSide.sign('test_message', 'base64')

console.log(result)

var serverSide = new NodeRSA({ b: 512 });
serverSide.importKey(publicKey, 'pkcs8-public');
console.log(serverSide.verify('test_message', new Buffer(result, 'base64')))

And the output for it is 它的输出是

baU/46UJYUp6Xt6sYs306t1vQdUOBRg10YuJPKspwLYj3aJHMgeQXMSfvBKvS+PJ3CMSVMVVjvoweNRu7A6ZzCSyVub9+qv0u5/2vSdUqiLDSHP5Gj9CRxsWPTLnapS27CJh3ywhqfgkuOSt6RZYTXqqoraHMP2jmGjfdLQmJbPiWamOc20u7xeTHK8oRmpXV0Pi5w4+7E6CkyfF9EfpLmmGGYiKqOWriWhYFbqkp+OV7FY4WRN1KwtmcZcnlWZ/4wAzg9uDL+8ZGyWKq62JY6Ee8LO5u6FCG7lU3KqBdq4eFKYI3CM9wdrxoZ7kNUlq0tQGZQ++MihdZQOfwj1vSA==

true

So with that code snippet I'm able to sign and verify the message. 因此,使用该代码段,我能够签名并验证消息。 However, I'm not able to verify the signed message with the following Go snippet. 但是,我无法使用以下Go片段验证已签名的邮件。

package main

import (
  "crypto"
  "crypto/rsa"
  "crypto/x509"
  "encoding/base64"
  "encoding/pem"
  "errors"
  "fmt"
  "os"
)

func main() {

  toSign := "test_message"

  signed, err := base64.StdEncoding.DecodeString("baU/46UJYUp6Xt6sYs306t1vQdUOBRg10YuJPKspwLYj3aJHMgeQXMSfvBKvS+PJ3CMSVMVVjvoweNRu7A6ZzCSyVub9+qv0u5/2vSdUqiLDSHP5Gj9CRxsWPTLnapS27CJh3ywhqfgkuOSt6RZYTXqqoraHMP2jmGjfdLQmJbPiWamOc20u7xeTHK8oRmpXV0Pi5w4+7E6CkyfF9EfpLmmGGYiKqOWriWhYFbqkp+OV7FY4WRN1KwtmcZcnlWZ/4wAzg9uDL+8ZGyWKq62JY6Ee8LO5u6FCG7lU3KqBdq4eFKYI3CM9wdrxoZ7kNUlq0tQGZQ++MihdZQOfwj1vSA==")
  if err != nil {
    println("unable do decode")
    os.Exit(1)
  }

  parser, err := loadPublicKey()
  if err != nil {
    println("unable to load public key")
    os.Exit(1)
  }

  err = parser.Unsign([]byte(toSign), signed)
  if err != nil {
    println("unable to verify")
    os.Exit(1)
  }

}

func loadPublicKey() (Unsigner, error) {

  return parsePublicKey([]byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj1IEeouqDYiMX0rMiPAI
64UntzNxE01+tB+k+aKesHzVXE5AGnyWHIFdrByfjR93CMh3y56xsL78VP1/Xp8i
VmAnbiFN5kpmawJ1owhDvNIl8A+QUiDzMg0z/yepzjp61Dg4CUFzGrmTfYO1aMWy
WhR0ZKfy+HvVaGjpod2ioScU7FkzeO+fDR85quLFta7OXDwqD4NCPYeZTS5fgK1N
n72nrItoj5e36fzWvZntfvi4NHt7nqOj4VH5e5YJHvmLWHh5Swh+OVyIAwhxYSK5
PSupicGG8ixVy75hkjzZ2vW5JdVWMPYbVUMpqjtE+i1zQTYNJ36hM/zznZR/drU7
UwIDAQAB
-----END PUBLIC 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)
}

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

func (r *rsaPublicKey) Unsign(message []byte, sig []byte) error {
  var opts rsa.PSSOptions
  opts.SaltLength = rsa.PSSSaltLengthAuto
  PSSmessage := message
  newhash := crypto.SHA256
  pssh := newhash.New()
  pssh.Write(PSSmessage)
  hashed := pssh.Sum(nil)
  return rsa.VerifyPSS(r.PublicKey, newhash, hashed, sig, &opts)
}

The snippet was found and a little bit modified from other answers, however I can't make it work. 该片段被发现,并从其他答案稍作修改,但我无法使其工作。

From the Node-RSA pages : Node-RSA页面

signingScheme — scheme used for signing and verifying. signingScheme - 用于签名和验证的方案。 Can be 'pkcs1' or 'pss' or 'scheme-hash' format string (eg 'pss-sha1' ). 可以是'pkcs1''pss'或'scheme-hash'格式字符串(例如'pss-sha1' )。 Default 'pkcs1-sha256' , or, if chosen pss: 'pss-sha1' . 默认为'pkcs1-sha256' ,或者,如果选择了pss: 'pss-sha1'

So the NodeJS implementation uses PKCS#1 v1.5 padding with SHA-256 while Go uses PSS padding with SHA-256. 因此,NodeJS实现使用带有SHA-256的PKCS#1 v1.5填充,而Go使用带有SHA-256的PSS填充。

You basically need to make sure that your signature algorithms and their parameters match. 您基本上需要确保您的签名算法及其参数匹配。 Note that you may also want to make sure that the hash function used for MGF1 (the mask generation function within PSS) matches if you go for PSS and the code keeps failing. 请注意,如果您使用PSS并且代码仍然失败,您可能还需要确保用于MGF1的哈希函数(PSS中的掩码生成函数)匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM