How to validate zonefile hash via RIPEMD160(SHA256(data))

@aaron , @jude

I’m trying to manually verify my zonefile in javascript but I cannot get the hashes to match:

This is my payload for the zonefile https://core.blockstack.org/v1/names/nicktee.id :

{
  "address": "17xxYBCvxwrwKtAna4bubsxGCMCcVNAgyw", 
  "blockchain": "bitcoin", 
  "expire_block": 620924, 
  "last_txid": "bd94ab4e5ebc63d6a73e32d399d1007572a2d25ead5f6af63d7d1bf73cfa4619", 
  "status": "registered", 
  "zonefile": "$ORIGIN nicktee.id\n$TTL 3600\ntest2\tIN\tTXT\t\"owner=1JZQMpjPEzSM8AF7LuEkLVs7Yqk8ekautP\" \"seqn=0\" \"parts=1\" \"zf0=e3NpZ25hdHVyZTogIklIeHRZaVhHbmZ4MGxCVFFISmJiV083UW8ya2g4WWtsemNpZ2lZdVcxVXB6Vk5HUnBxZFAyR2pObXE2S21WRENtcnBvSW5LRjhMTVdVMGZCM2V6eHRHSSIsIGhhc2g6ICIzTWYxVVNtUWNzTTZiUGtIQjExc3NvQTZ0OTUzMWpxNXdUZTRwcUppckJJIiB9\"\ne0fdbffb-f916-e71d-b729-464a9709be14\tIN\tTXT\t\"owner=18A9iyBWn68BW7AVRvSWHLJ81dsmMtt9hJ\" \"seqn=0\" \"parts=1\" \"zf0=e3NpZ25hdHVyZTogIklIeHRZaVhHbmZ4MGxCVFFISmJiV083UW8ya2g4WWtsemNpZ2lZdVcxVXB6Vk5HUnBxZFAyR2pObXE2S21WRENtcnBvSW5LRjhMTVdVMGZCM2V6eHRHSSIsIGhhc2g6ICIzTWYxVVNtUWNzTTZiUGtIQjExc3NvQTZ0OTUzMWpxNXdUZTRwcUppckJJIiB9\"\ne0fdbffb-f916-e71d-b729-464a9709be17\tIN\tTXT\t\"owner=12rzFbu2zENnoiJTVEhckZZ4TT8B2Rq8me\" \"seqn=0\" \"parts=1\" \"zf0=JE9SSUdJTiBlMGZkYmZmYi1mOTE2LWU3MWQtYjcyOS00NjRhOTcwOWJlMTcKJFRUTCAzNjAwCl9odHRwcy5fdGNwIFVSSSAxMCAxICJodHRwczovL2dhaWEuYmxvY2tzdGFjay5vcmcvaHViLzE3YXFkWHRldEszUTJYd2lhU21tQ29RYzR6MzhiRzl5dVYvcHJvZmlsZS5qc29uIgo=\"\ne0fdbffb-f916-e71d-b729-464a9709be15\tIN\tTXT\t\"owner=13CU6YEpXUqaDbw2NtBjrL9QBfmJn48zEz\" \"seqn=0\" \"parts=1\" \"zf0=JE9SSUdJTiBlMGZkYmZmYi1mOTE2LWU3MWQtYjcyOS00NjRhOTcwOWJlMTUKJFRUTCAzNjAwCmhhc2ggVFhUIDNNZjFVU21RY3NNNmJQa0hCMTFzc29BNnQ5NTMxanE1d1RlNHBxSmlyQkkK\"\n_http._tcp\tIN\tURI\t10\t1\t\"https://gaia.blockstack.org/hub/17xxYBCvxwrwKtAna4bubsxGCMCcVNAgyw/profile.json\"\n", 
  "zonefile_hash": "065cc6668d8d23ca46ca94144a268fd442a356cb"
}

I pulled in this JS lib https://github.com/crypto-browserify/crypto-browserify

here is my code

var crypto = require('crypto')

var zonefile = '$ORIGIN nicktee.id\n$TTL 3600\ntest2\tIN\tTXT\t\"owner=1JZQMpjPEzSM8AF7LuEkLVs7Yqk8ekautP\" \"seqn=0\" \"parts=1\" \"zf0=e3NpZ25hdHVyZTogIklIeHRZaVhHbmZ4MGxCVFFISmJiV083UW8ya2g4WWtsemNpZ2lZdVcxVXB6Vk5HUnBxZFAyR2pObXE2S21WRENtcnBvSW5LRjhMTVdVMGZCM2V6eHRHSSIsIGhhc2g6ICIzTWYxVVNtUWNzTTZiUGtIQjExc3NvQTZ0OTUzMWpxNXdUZTRwcUppckJJIiB9\"\ne0fdbffb-f916-e71d-b729-464a9709be14\tIN\tTXT\t\"owner=18A9iyBWn68BW7AVRvSWHLJ81dsmMtt9hJ\" \"seqn=0\" \"parts=1\" \"zf0=e3NpZ25hdHVyZTogIklIeHRZaVhHbmZ4MGxCVFFISmJiV083UW8ya2g4WWtsemNpZ2lZdVcxVXB6Vk5HUnBxZFAyR2pObXE2S21WRENtcnBvSW5LRjhMTVdVMGZCM2V6eHRHSSIsIGhhc2g6ICIzTWYxVVNtUWNzTTZiUGtIQjExc3NvQTZ0OTUzMWpxNXdUZTRwcUppckJJIiB9\"\ne0fdbffb-f916-e71d-b729-464a9709be17\tIN\tTXT\t\"owner=12rzFbu2zENnoiJTVEhckZZ4TT8B2Rq8me\" \"seqn=0\" \"parts=1\" \"zf0=JE9SSUdJTiBlMGZkYmZmYi1mOTE2LWU3MWQtYjcyOS00NjRhOTcwOWJlMTcKJFRUTCAzNjAwCl9odHRwcy5fdGNwIFVSSSAxMCAxICJodHRwczovL2dhaWEuYmxvY2tzdGFjay5vcmcvaHViLzE3YXFkWHRldEszUTJYd2lhU21tQ29RYzR6MzhiRzl5dVYvcHJvZmlsZS5qc29uIgo=\"\ne0fdbffb-f916-e71d-b729-464a9709be15\tIN\tTXT\t\"owner=13CU6YEpXUqaDbw2NtBjrL9QBfmJn48zEz\" \"seqn=0\" \"parts=1\" \"zf0=JE9SSUdJTiBlMGZkYmZmYi1mOTE2LWU3MWQtYjcyOS00NjRhOTcwOWJlMTUKJFRUTCAzNjAwCmhhc2ggVFhUIDNNZjFVU21RY3NNNmJQa0hCMTFzc29BNnQ5NTMxanE1d1RlNHBxSmlyQkkK\"\n_http._tcp\tIN\tURI\t10\t1\t\"https://gaia.blockstack.org/hub/17xxYBCvxwrwKtAna4bubsxGCMCcVNAgyw/profile.json\"\n';
var sha256 = crypto.createHash('sha256').update(zonefile).digest('hex')
var rmd160ofsha256 = crypto.createHash('rmd160').update(sha256).digest('hex');
console.log(rmd160ofsha256); // ec82e079e7e9f26212aada41625ad41055708d79

The result ec82e079e7e9f26212aada41625ad41055708d79 is not equal to “zonefile_hash” in the payload 065cc6668d8d23ca46ca94144a268fd442a356cb

Any ideas?

You’re hashing the hex-encoded sha256 hash in the ripemd160. You need to hash the “raw” sha256 hash.

Do this instead:

var sha256 = crypto.createHash('sha256').update(zonefile).digest()

(notice the lack of a “hex” argument in the digest).

it worked! thanks a ton @jude

Out of curiosity what does the beginning of the hash in the OP_RETURN represent?

RETURN PUSHDATA(39)[69642b86c65443161f43cf1d59f7d15da3f19c22c48dc673d93ac1208cf1f65528873706a33f73]

Got you covered: https://github.com/blockstack/blockstack-core/blob/master/docs/wire-format.md#name_update

1 Like