验证在Java中的golang中生成的rsa.SignPKCS1v15签名 [英] Verify rsa.SignPKCS1v15 signature generated in golang in Java
问题描述
我试图让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屋!