java - 在Java中验证golang生成的rsa.SignPKCS1v15签名

标签 java android go rsa bouncycastle

我试图让 Java 验证签名的 SHA-1 哈希,但它一直返回 false。我在 Go 中有以下代码,它生成一个 RSA key 对并签名并返回任何命中/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 的字节不应该是 hashedBytes,而是 inputBytes。

关于java - 在Java中验证golang生成的rsa.SignPKCS1v15签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29422738/

相关文章:

.htaccess - 没有 Nginx 或 Apache 的 Golang htaccess 配置

java - 如何将参数从另一个类传递给非静态方法?

java - Selenium Marionette 驱动程序在第二次启动时出现 UnreachableBrowserException

Android X + Truth + Guava 测试编译问题

android - 新的 UNEXPECTED TOP-LEVEL EXCEPTION 。再次出现在《SOF》中。

go - 基于 mgo 中的正则表达式的搜索未给出所需的结果

java - 在 Hibernate 中更新表时出现 "Not mapped"异常

java - 当启用/禁用 JButton 的子类时,我可以重写什么方法来触发事件

Android Workmanager PeriodicWorkRequest API 只能工作一次吗?

unit-testing - 用于 http 处理程序测试的 Golang 模拟函数