验证在Java中的golang中生成的rsa.SignPKCS1v15签名 [英] Verify rsa.SignPKCS1v15 signature generated in golang in Java

查看:983
本文介绍了验证在Java中的golang中生成的rsa.SignPKCS1v15签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让Java来验证已签名的SHA-1哈希,但它一直返回false。 Go中有以下代码,它生成一个RSA密钥对,并签署并返回任何符合/符号端点的消息以及十六进制编码哈希和公钥模数和指数:

  package main 

import(
crypto
crypto / rand
crypto / rsa
encoding / hex
encoding / json
fmt
io
net / http
strconv


var PrivKey * rsa.PrivateKey

类型消息struct {
消息字符串`json:消息``
}

func(msg * Message)解码(r io.Reader)错误{
返回json.NewDecoder(r).Decode(&msg)
}

类型签名struct {
哈希字符串`json:hash`
签名字符串`json:签名`
N字符串`json:N`
E字符串`json:E`
}

func hash(msg string)[] byte {
sh:= crypto.SHA1.New()
sh。写([]字节(msg))
hash:= sh.Sum(nil)
return hash
}

func SignWithKey(msg Message)Signature {
hash:= hash(msg.Message)
字节,err:= rsa.SignPKCS1v15(rand.Reader,PrivKey,crypto.SHA1,hash)
if err!= nil {
panic(err)
}
签名:= hex.EncodeToString(字节)
sig:=签名{
十六进制.EncodeToString(哈希),
签名,
PrivKey.PublicKey.N.String(),
strconv.Itoa(PrivKey.PublicKey.E),
}
返回sig
}

func sign(w http.ResponseWriter,r * http .Request){
fmt.Println(/ sign)
var msg消息
err:= msg.Decode(r.Body)
if err!= nil {
$恐慌(错误)
}

fmt.Println(Signing:+ msg.Message)
签名:= SignWithKey(msg)
js, err:= json.Marshal(签名)
fmt.Println(string(js))

w.Header()。Set(Content-Type,application / json)
w.Write(js)
}

func LoadKeys(){
//产生私钥
var err错误
PrivKey,err = rsa。 GenerateKey(rand.Reader,2048)
if err!= nil {
fmt.Println(err)
}
}

func main() {
$ b fmt.Println(加载密钥)
LoadKeys()
fmt.Println(已加载密钥)
http.HandleFunc(/ sign ,sign)

http.ListenAndServe(:8080,nil)
}

在Java / Android端,我有这样的代码,它在发送相关位后使用未解析的JSON对象访问此函数,但一旦它到达Signature验证部分,它总是返回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);

尝试{
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);

签名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());




解决方案

I am trying to get Java to verify a signed SHA-1 hash but it keeps returning false. I have the following code in Go which generates an RSA Key Pair and signs and returns any message that hits the /sign endpoint along with the hex encoded hash and the public key modulus and exponent:

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

On the Java/Android side I have this code which after sending the relevant bits hits this function with the unparsed JSON object, but once it gets to the Signature verify part it always returns 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());
            }  
        }
    }

解决方案

In Java you don't need to hash the message before signing or verifying it. That means that the bytes being sent to sig.update shouldn't be hashedBytes, but the inputBytes.

这篇关于验证在Java中的golang中生成的rsa.SignPKCS1v15签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆