我试图让Java验证签名的SHA-1哈希,但是它一直返回false。我在Go中有以下代码,该代码生成RSA密钥对并签名并返回击中/ sign端点的任何消息,以及十六进制编码的哈希,公钥模数和指数:
package main import ( "crypto" "crypto/rand" "crypto/rsa" "encoding/hex" "encoding/json" "fmt" "io" "net/http" "strconv" ) var PrivKey *rsa.PrivateKey type Message struct { Message string `json:"message"` } func (msg *Message) Decode(r io.Reader) error { return json.NewDecoder(r).Decode(&msg) } type Signature struct { Hash string `json:"hash"` Signature string `json:"signature"` N string `json:"N"` E string `json:"E"` } func hash(msg string) []byte { sh := crypto.SHA1.New() sh.Write([]byte(msg)) hash := sh.Sum(nil) return hash } func SignWithKey(msg Message) Signature { hash := hash(msg.Message) bytes, err := rsa.SignPKCS1v15(rand.Reader, PrivKey, crypto.SHA1, hash) if err != nil { panic(err) } signature := hex.EncodeToString(bytes) sig := Signature{ hex.EncodeToString(hash), signature, PrivKey.PublicKey.N.String(), strconv.Itoa(PrivKey.PublicKey.E), } return sig } func sign(w http.ResponseWriter, r *http.Request) { fmt.Println("/sign") var msg Message err := msg.Decode(r.Body) if err != nil { panic(err) } fmt.Println("Signing: " + msg.Message) signature := SignWithKey(msg) js, err := json.Marshal(signature) fmt.Println(string(js)) w.Header().Set("Content-Type", "application/json") w.Write(js) } func LoadKeys() { // generate private key var err error PrivKey, err = rsa.GenerateKey(rand.Reader, 2048) if err != nil { fmt.Println(err) } } func main() { fmt.Println("Loading Keys") LoadKeys() fmt.Println("Keys Loaded") http.HandleFunc("/sign", sign) http.ListenAndServe(":8080", nil) }
在Java / Android方面,我有以下代码,该代码在发送相关位后会使用未解析的JSON对象击中此函数,但是一旦到达签名验证部分,它始终会返回false:
protected void onPostExecute(String result) { if (result == null) { tv.setText("NULL"); return; } JsonElement jelement = new JsonParser().parse(result); JsonObject jobject = jelement.getAsJsonObject(); String signature = jobject.getAsJsonPrimitive("signature").getAsString(); BigInteger N = jobject.getAsJsonPrimitive("N").getAsBigInteger(); BigInteger E = jobject.getAsJsonPrimitive("E").getAsBigInteger(); String hash = jobject.getAsJsonPrimitive("hash").getAsString(); java.security.spec.RSAPublicKeySpec spec = new java.security.spec.RSAPublicKeySpec(N, E); try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pk = keyFactory.generatePublic(spec); MessageDigest digest = MessageDigest.getInstance("SHA1"); byte[] inputBytes = msg.getBytes("UTF8"); byte[] hashedBytes = digest.digest(inputBytes); Signature sig = Signature.getInstance("SHA1withRSA", "SC"); sig.initVerify( pk ); sig.update( hashedBytes ); boolean ret = sig.verify( Hex.decode(signature) ); if (ret) { tv.setText(output + "Verified"); } else { tv.setText(output + "NOT VERIFIED"); } } catch (Exception e) { Log.i("error", e.toString()); } } }
在Java中,您无需在签名或验证消息之前对消息进行哈希处理。这意味着发送到sig.update的字节不应为hashBytes,而应为inputBytes。