验证在Golang中生成的rsa.SignPKCS1v15签名在Java中的验证。

huangapple go评论129阅读模式
英文:

Verify rsa.SignPKCS1v15 signature generated in golang in Java

问题

我正在尝试让Java验证一个已签名的SHA-1哈希值,但它始终返回false。我在Go中有以下代码,它生成一个RSA密钥对,并对命中/sign端点的任何消息进行签名并返回带有十六进制编码的哈希、公钥模数和指数的消息:

  1. package main
  2. import (
  3. "crypto"
  4. "crypto/rand"
  5. "crypto/rsa"
  6. "encoding/hex"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "net/http"
  11. "strconv"
  12. )
  13. var PrivKey *rsa.PrivateKey
  14. type Message struct {
  15. Message string `json:"message"`
  16. }
  17. func (msg *Message) Decode(r io.Reader) error {
  18. return json.NewDecoder(r).Decode(&msg)
  19. }
  20. type Signature struct {
  21. Hash string `json:"hash"`
  22. Signature string `json:"signature"`
  23. N string `json:"N"`
  24. E string `json:"E"`
  25. }
  26. func hash(msg string) []byte {
  27. sh := crypto.SHA1.New()
  28. sh.Write([]byte(msg))
  29. hash := sh.Sum(nil)
  30. return hash
  31. }
  32. func SignWithKey(msg Message) Signature {
  33. hash := hash(msg.Message)
  34. bytes, err := rsa.SignPKCS1v15(rand.Reader, PrivKey, crypto.SHA1, hash)
  35. if err != nil {
  36. panic(err)
  37. }
  38. signature := hex.EncodeToString(bytes)
  39. sig := Signature{
  40. hex.EncodeToString(hash),
  41. signature,
  42. PrivKey.PublicKey.N.String(),
  43. strconv.Itoa(PrivKey.PublicKey.E),
  44. }
  45. return sig
  46. }
  47. func sign(w http.ResponseWriter, r *http.Request) {
  48. fmt.Println("/sign")
  49. var msg Message
  50. err := msg.Decode(r.Body)
  51. if err != nil {
  52. panic(err)
  53. }
  54. fmt.Println("Signing: " + msg.Message)
  55. signature := SignWithKey(msg)
  56. js, err := json.Marshal(signature)
  57. fmt.Println(string(js))
  58. w.Header().Set("Content-Type", "application/json")
  59. w.Write(js)
  60. }
  61. func LoadKeys() {
  62. // generate private key
  63. var err error
  64. PrivKey, err = rsa.GenerateKey(rand.Reader, 2048)
  65. if err != nil {
  66. fmt.Println(err)
  67. }
  68. }
  69. func main() {
  70. fmt.Println("Loading Keys")
  71. LoadKeys()
  72. fmt.Println("Keys Loaded")
  73. http.HandleFunc("/sign", sign)
  74. http.ListenAndServe(":8080", nil)
  75. }

在Java/Android端,我有以下代码,它在发送相关部分后,使用未解析的JSON对象调用此函数,但一旦到达签名验证部分,它总是返回false:

  1. protected void onPostExecute(String result) {
  2. if (result == null) {
  3. tv.setText("NULL");
  4. return;
  5. }
  6. JsonElement jelement = new JsonParser().parse(result);
  7. JsonObject jobject = jelement.getAsJsonObject();
  8. String signature = jobject.getAsJsonPrimitive("signature").getAsString();
  9. BigInteger N = jobject.getAsJsonPrimitive("N").getAsBigInteger();
  10. BigInteger E = jobject.getAsJsonPrimitive("E").getAsBigInteger();
  11. String hash = jobject.getAsJsonPrimitive("hash").getAsString();
  12. java.security.spec.RSAPublicKeySpec spec = new java.security.spec.RSAPublicKeySpec(N, E);
  13. try {
  14. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  15. PublicKey pk = keyFactory.generatePublic(spec);
  16. MessageDigest digest = MessageDigest.getInstance("SHA1");
  17. byte[] inputBytes = msg.getBytes("UTF8");
  18. byte[] hashedBytes = digest.digest(inputBytes);
  19. Signature sig = Signature.getInstance("SHA1withRSA", "SC");
  20. sig.initVerify(pk);
  21. sig.update(hashedBytes);
  22. boolean ret = sig.verify(Hex.decode(signature));
  23. if (ret) {
  24. tv.setText(output + "Verified");
  25. } else {
  26. tv.setText(output + "NOT VERIFIED");
  27. }
  28. } catch (Exception e) {
  29. Log.i("error", e.toString());
  30. }
  31. }

请问有什么我可以帮助你的吗?

英文:

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:

  1. package main
  2. import (
  3. "crypto"
  4. "crypto/rand"
  5. "crypto/rsa"
  6. "encoding/hex"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "net/http"
  11. "strconv"
  12. )
  13. var PrivKey *rsa.PrivateKey
  14. type Message struct {
  15. Message string `json:"message"`
  16. }
  17. func (msg *Message) Decode(r io.Reader) error {
  18. return json.NewDecoder(r).Decode(&msg)
  19. }
  20. type Signature struct {
  21. Hash string `json:"hash"`
  22. Signature string `json:"signature"`
  23. N string `json:"N"`
  24. E string `json:"E"`
  25. }
  26. func hash(msg string) []byte {
  27. sh := crypto.SHA1.New()
  28. sh.Write([]byte(msg))
  29. hash := sh.Sum(nil)
  30. return hash
  31. }
  32. func SignWithKey(msg Message) Signature {
  33. hash := hash(msg.Message)
  34. bytes, err := rsa.SignPKCS1v15(rand.Reader, PrivKey, crypto.SHA1, hash)
  35. if err != nil {
  36. panic(err)
  37. }
  38. signature := hex.EncodeToString(bytes)
  39. sig := Signature{
  40. hex.EncodeToString(hash),
  41. signature,
  42. PrivKey.PublicKey.N.String(),
  43. strconv.Itoa(PrivKey.PublicKey.E),
  44. }
  45. return sig
  46. }
  47. func sign(w http.ResponseWriter, r *http.Request) {
  48. fmt.Println("/sign")
  49. var msg Message
  50. err := msg.Decode(r.Body)
  51. if err != nil {
  52. panic(err)
  53. }
  54. fmt.Println("Signing: " + msg.Message)
  55. signature := SignWithKey(msg)
  56. js, err := json.Marshal(signature)
  57. fmt.Println(string(js))
  58. w.Header().Set("Content-Type", "application/json")
  59. w.Write(js)
  60. }
  61. func LoadKeys() {
  62. // generate private key
  63. var err error
  64. PrivKey, err = rsa.GenerateKey(rand.Reader, 2048)
  65. if err != nil {
  66. fmt.Println(err)
  67. }
  68. }
  69. func main() {
  70. fmt.Println("Loading Keys")
  71. LoadKeys()
  72. fmt.Println("Keys Loaded")
  73. http.HandleFunc("/sign", sign)
  74. http.ListenAndServe(":8080", nil)
  75. }

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:

  1. protected void onPostExecute(String result) {
  2. if (result == null) {
  3. tv.setText("NULL");
  4. return;
  5. }
  6. JsonElement jelement = new JsonParser().parse(result);
  7. JsonObject jobject = jelement.getAsJsonObject();
  8. String signature = jobject.getAsJsonPrimitive("signature").getAsString();
  9. BigInteger N = jobject.getAsJsonPrimitive("N").getAsBigInteger();
  10. BigInteger E = jobject.getAsJsonPrimitive("E").getAsBigInteger();
  11. String hash = jobject.getAsJsonPrimitive("hash").getAsString();
  12. java.security.spec.RSAPublicKeySpec spec = new java.security.spec.RSAPublicKeySpec(N, E);
  13. try {
  14. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  15. PublicKey pk = keyFactory.generatePublic(spec);
  16. MessageDigest digest = MessageDigest.getInstance("SHA1");
  17. byte[] inputBytes = msg.getBytes("UTF8");
  18. byte[] hashedBytes = digest.digest(inputBytes);
  19. Signature sig = Signature.getInstance("SHA1withRSA", "SC");
  20. sig.initVerify( pk );
  21. sig.update( hashedBytes );
  22. boolean ret = sig.verify( Hex.decode(signature) );
  23. if (ret) {
  24. tv.setText(output + "Verified");
  25. } else {
  26. tv.setText(output + "NOT VERIFIED");
  27. }
  28. }
  29. catch (Exception e) {
  30. Log.i("error", e.toString());
  31. }
  32. }
  33. }

答案1

得分: 2

在Java中,您在签名或验证消息之前不需要对其进行哈希处理。这意味着发送到sig.update的字节不应该是hashedBytes,而是inputBytes。

英文:

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.

答案2

得分: 0

如果您不想在Go中对内容进行哈希处理,而只是对原始数据进行签名,您可以使用以下代码:

  1. signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.Hash(0), []byte(message))
英文:

If you don't want to hash the content in Go and just sign the raw data, you can use this code:

  1. signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.Hash(0), []byte(message))

huangapple
  • 本文由 发表于 2015年4月3日 05:25:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/29422738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定