dns: SIG(0) with ED25519 panic: crypto: requested hash function #0 is unavailable

Learning how to use this comprehensive library, Sign() in snippet

        pk, err := keyRR.Generate(256)
        now := uint32(time.Now().Unix())
        sig0RR := new(dns.SIG)
        sig0RR.Hdr.Name = "."
        sig0RR.Hdr.Rrtype = dns.TypeSIG
        sig0RR.Hdr.Class = dns.ClassANY
        sig0RR.Algorithm = uint8(dns.ED25519)
        sig0RR.Expiration = now + 300
        sig0RR.Inception = now - 300
        sig0RR.KeyTag = keyRR.KeyTag()
        sig0RR.SignerName = keyRR.Hdr.Name
        mb, err := sig0RR.Sign(pk.(crypto.Signer), m)

and variations has resulted in a panic condition

panic: crypto: requested hash function #0 is unavailable

goroutine 1 [running]:
crypto.Hash.New(0x64bce0)
        /home/go/src/crypto/crypto.go:134 +0x99
github.com/miekg/dns.(*SIG).Sign(0xc000072540, {0x7f6c085d7980, 0xc00000e180}, 0xc000161ec8)
        /home/go/src/github.com/miekg/dns/sig0.go:46 +0x205
main.main()
        /home/src/test_go/update.go:129 +0xed9
exit status 2

Doubting my code, I locally patched sig0_test.go to test ED25519 with

diff --git a/sig0_test.go b/sig0_test.go
index 1abdc4af..3f4fb04f 100644
--- a/sig0_test.go
+++ b/sig0_test.go
@@ -12,7 +12,7 @@ func TestSIG0(t *testing.T) {
        }
        m := new(Msg)
        m.SetQuestion("example.org.", TypeSOA)
-       for _, alg := range []uint8{ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
+       for _, alg := range []uint8{ED25519, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
                algstr := AlgorithmToString[alg]
                keyrr := new(KEY)
                keyrr.Hdr.Name = algstr + "."
@@ -27,6 +27,8 @@ func TestSIG0(t *testing.T) {
                        keysize = 384
                case RSASHA512:
                        keysize = 1024
+               case ED25519:
+                       keysize = 256
                }
                pk, err := keyrr.Generate(keysize)
                if err != nil {

but invoking go test -run SIG0 -v also results in a similar panic condition

=== RUN   TestSIG0
--- FAIL: TestSIG0 (0.00s)
panic: crypto: requested hash function #0 is unavailable [recovered]
        panic: crypto: requested hash function #0 is unavailable

goroutine 19 [running]:
testing.tRunner.func1.2({0x709dc0, 0xc0000998c0})
        /home/go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
        /home/go/src/testing/testing.go:1212 +0x218
panic({0x709dc0, 0xc0000998c0})
        /home/go/src/runtime/panic.go:1038 +0x215
crypto.Hash.New(0x716860)
        /home/go/src/crypto/crypto.go:134 +0x99
github.com/miekg/dns.(*SIG).Sign(0xc0000a63c0, {0x7ddfe8, 0xc0000b6120}, 0x7d53ce)
        /home/src/dns/sig0.go:46 +0x205
github.com/miekg/dns.TestSIG0(0xc000083860)
        /home/src/dns/sig0_test.go:48 +0x3db
testing.tRunner(0xc000083860, 0x787258)
        /home/go/src/testing/testing.go:1259 +0x102
created by testing.(*T).Run
        /home/go/src/testing/testing.go:1306 +0x35a
exit status 2
FAIL    github.com/miekg/dns    0.007s

A quick search suggests the following to be triggering the panic in the crypt library?

https://github.com/miekg/dns/blob/84af068d469b2c93521aaa1d88745b613ac77a5d/sig0.go#L41 https://github.com/miekg/dns/blob/84af068d469b2c93521aaa1d88745b613ac77a5d/dnssec.go#L67-L78

Noting this comment, is there a mechanism by which ED25519 can work with SIG(0)?

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 22 (9 by maintainers)

Most upvoted comments

OK. I think my previous issues were issues fixed in my code and config.

Using this branch, I can now report code using it both passes the verification code modified from sig0_test.go, as well as a BIND9 server accepting sig(0) signed messages without error, eg:

2022/02/13 19:30:55 -- Send DNS message --
2022/02/13 19:30:55 ;; opcode: UPDATE, status: NOERROR, id: 54061
;; flags:; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;example.com.       IN       SOA

;; AUTHORITY SECTION:
go-dns-test.example.com.    600     IN      A       127.0.0.4

;; ADDITIONAL SECTION:
.       0       CLASS255        SIG     None 15 0 0 20220213183555 20220213182555 56161 ed25519. TaVoDzjs/gMihwVR3frJ33o9f/4LTta/4oJA0sQiesPoAUHYArFLOMrig2VJ0+YQ7nMyESz6WwAMywJPPVouAg==

2022/02/13 19:30:55  ***  DNS response from server ns0.example.com for zone (example.com) reports success
2022/02/13 19:30:55 -- Answer --
2022/02/13 19:30:55 ;; opcode: UPDATE, status: NOERROR, id: 54061
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;example.com.       IN       SOA

So initial tests are looking good so far.

Thanks for your effort so far in resolving this issue!

It looks like SIG0 was overlooked when ED25519 was introduced. Both SIG’s Sign and Verify functions will need updating to do the same special casing RRSIG’s Sign does. It might make sense to introduce an internal null hash.Hash to make the code less gnarly.

[ Quoting @.***> in “Re: [miekg/dns] SIG(0) with ED25519…” ]

If it’s implemented elsewhere, then we can do it. I don’t like that it’s not documented though. I guess we just have to live with that.

thought about that too. I feel this PR (or follow up) should document some of the things said in this thread and say more about sig(0) and maybe a bit about dnssec as well.