package sign

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

// RsaPrivateKey is a holder of RSA private key
type RsaPrivateKey struct {
   *rsa.PrivateKey
}

// Signer is an interface to define signature action(s)
type Signer interface {
   Sign(data []byte) ([]byte, error)
}

//Sign is the signature method
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)
}

// LoadPrivateKey for load private key with file path
func LoadPrivateKey(path string) (Signer, error) {
   fileBytes, e := ioutil.ReadFile(path)
   if e != nil {
      return nil, fmt.Errorf("could not load private key: %v", e)
   }
   return ParsePrivateKey(fileBytes)
}

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

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

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

//RsaPublicKey is a holder of RSA public key
type RsaPublicKey struct {
   *rsa.PublicKey
}

//Verifier is an interface to define signature verification action(s)
type Verifier interface {
   Verify(data []byte, sig []byte) error
}

//Verify is the verification method
func (r *RsaPublicKey) Verify(message []byte, sig []byte) error {
   h := sha256.New()
   h.Write(message)
   d := h.Sum(nil)
   return rsa.VerifyPKCS1v15(r.PublicKey, crypto.SHA256, d, sig)
}

//LoadTupuPublicKey for load embeded TUPU's public key
func LoadTupuPublicKey() (Verifier, error) {
   return parsePublicKey([]byte(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDyZneSY2eGnhKrArxaT6zswVH9
/EKz+CLD+38kJigWj5UaRB6dDUK9BR6YIv0M9vVQZED2650tVhS3BeX04vEFhThn
NrJguVPidufFpEh3AgdYDzOQxi06AN+CGzOXPaigTurBxZDIbdU+zmtr6a8bIBBj
WQ4v2JR/BA6gVHV5TwIDAQAB
-----END PUBLIC KEY-----`))
}

func parsePublicKey(pemBytes []byte) (Verifier, 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 newVerifierFromKey(rawkey)
}

func newVerifierFromKey(k interface{}) (Verifier, error) {
   var sshKey Verifier
   switch t := k.(type) {
   case *rsa.PublicKey:
      sshKey = &RsaPublicKey{t}
   default:
      return nil, fmt.Errorf("ssh: unsupported key type %T", k)
   }
   return sshKey, nil
}
package sign

import (
   "encoding/base64"
   "encoding/json"
   "log"
   "os"
   "testing"
)

var (
   PrivateKey = "./my_private_key.pem"
   PublicKey  = ``
   DATA = `{ "code": 0, "message": "success", "nonce": "0.01627771095362096", "timestamp": 1552391372490, "requestId": "tupu_request_id", "roomId": "your_room_id", "userId": "your_user_id", "forumId": "your_forum_id", "customInfo": {"hello": true, "other": "your customInfo"}, "5caee6b2a76925c55a09a6d2": { "label": "Politics", "review": false, "rate": 0.896484, "action": "block", "text": "毛泽东,你好", "violations": [{ "startTime": 12, "endTime": 15, "content": "毛泽东", "action": "block", "label": "Politics", "review": false, "rate": 0.896484, "speechUrl": "http:://123.mp3", "details": [{"keyword": "毛泽东", "hint": "毛泽东", "mainLabel": "Politics", "subLabel": "National_Leader"}] }] } }`
)

func Test_SignAndVerify_1(t *testing.T) {
   signer, err := LoadPrivateKey(PrivateKey)
   if err != nil {
      t.Fatal(err)
   }

   verifier, err := LoadTupuPublicKey()
   if err != nil {
      t.Fatal(err)
   }

   data := DATA
   sig, err := signer.Sign([]byte(data))
   if err != nil {
      log.Fatalf("error signing data: %v", err)
   }
   log.Println(base64.StdEncoding.EncodeToString(sig))

   err = verifier.Verify([]byte(data), sig)
   log.Println("test 1", err)

}

func Test_SignAndVerify_2(t *testing.T) {
   signer, err := ParsePrivateKey([]byte(PublicKey))
   if err != nil {
      t.Fatal(err)
   }

   verifier, err := LoadTupuPublicKey()
   if err != nil {
      t.Fatal(err)
   }

   data := DATA
   payload := make(map[string]interface{})
   err = json.Unmarshal([]byte(data), &payload)
   if err != nil {
      log.Fatalf("error unmarshalling data: %v", err)
   }

   byt, err := json.Marshal(payload)
   if err != nil {
      log.Fatalf("error marshalling data: %v", err)
   }
   err = os.WriteFile("./marshalled.txt", byt, os.ModePerm)
   if err != nil {
      log.Printf("error writing marshalled json to file: %v", err)
   }

   sig, err := signer.Sign(byt)
   if err != nil {
      log.Fatalf("error signing data: %v", err)
   }
   log.Println(base64.StdEncoding.EncodeToString(sig))

   err = verifier.Verify([]byte(data), sig)
   log.Println("test 2", err)

}

results matching ""

    No results matching ""