package main import ( "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/asn1" "encoding/base64" "encoding/json" "encoding/pem" "fmt" ) const KeyBitSize = 4096 // Приватный ключ - отдаётся серверу // Публичный ключ - сохраняется на клиенте func signRequest(req Request, key *rsa.PublicKey) (string, error) { body, _ := json.Marshal(req) based := base64.StdEncoding.EncodeToString(body) h := sha256.Sum256([]byte(based)) requestHash := fmt.Sprintf("%x", h) ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, key, []byte(requestHash)) if err != nil { return "", nil } signature := base64.StdEncoding.EncodeToString(ciphertext) return fmt.Sprintf("%s.%s", based, signature), nil } func parseKey(keyBytes []byte) (*rsa.PublicKey, error) { block, _ := pem.Decode(keyBytes) return x509.ParsePKCS1PublicKey(block.Bytes) } func generateKeys() (private []byte, public []byte, err error) { key, err := rsa.GenerateKey(rand.Reader, KeyBitSize) if err != nil { return nil, nil, err } var privateKey = &pem.Block{ Type: "PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), } asn1Bytes, _ := asn1.Marshal(key.PublicKey) var publicKey = &pem.Block{ Type: "PUBLIC KEY", Bytes: asn1Bytes, } bytePrivate := pem.EncodeToMemory(privateKey) bytePublic := pem.EncodeToMemory(publicKey) return bytePrivate, bytePublic, nil }