diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go
index c7c73a23ebd7..750be8572162 100644
--- a/cmd/geth/dbcmd.go
+++ b/cmd/geth/dbcmd.go
@@ -35,6 +35,7 @@ import (
 	"github.com/ethereum/go-ethereum/core/rawdb"
 	"github.com/ethereum/go-ethereum/core/state/snapshot"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/log"
 	"github.com/ethereum/go-ethereum/trie"
@@ -71,6 +72,7 @@ Remove blockchain and state databases`,
 			dbExportCmd,
 			dbMetadataCmd,
 			dbMigrateFreezerCmd,
+			dbCheckStateContentCmd,
 		},
 	}
 	dbInspectCmd = cli.Command{
@@ -83,6 +85,16 @@ Remove blockchain and state databases`,
 		Usage:       "Inspect the storage size for each type of data in the database",
 		Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
 	}
+	dbCheckStateContentCmd = cli.Command{
+		Action:    utils.MigrateFlags(checkStateContent),
+		Name:      "check-state-content",
+		ArgsUsage: "<start (optional)>",
+		Flags:     utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
+		Usage:     "Verify that state data is cryptographically correct",
+		Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
+For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
+a data corruption.`,
+	}
 	dbStatCmd = cli.Command{
 		Action: utils.MigrateFlags(dbStats),
 		Name:   "stats",
@@ -289,6 +301,60 @@ func inspect(ctx *cli.Context) error {
 	return rawdb.InspectDatabase(db, prefix, start)
 }
 
+func checkStateContent(ctx *cli.Context) error {
+	var (
+		prefix []byte
+		start  []byte
+	)
+	if ctx.NArg() > 1 {
+		return fmt.Errorf("Max 1 argument: %v", ctx.Command.ArgsUsage)
+	}
+	if ctx.NArg() > 0 {
+		if d, err := hexutil.Decode(ctx.Args().First()); err != nil {
+			return fmt.Errorf("failed to hex-decode 'start': %v", err)
+		} else {
+			start = d
+		}
+	}
+	stack, _ := makeConfigNode(ctx)
+	defer stack.Close()
+
+	db := utils.MakeChainDatabase(ctx, stack, true)
+	defer db.Close()
+	var (
+		it        = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
+		hasher    = crypto.NewKeccakState()
+		got       = make([]byte, 32)
+		errs      int
+		count     int
+		startTime = time.Now()
+		lastLog   = time.Now()
+	)
+	for it.Next() {
+		count++
+		v := it.Value()
+		k := it.Key()
+		hasher.Reset()
+		hasher.Write(v)
+		hasher.Read(got)
+		if !bytes.Equal(k, got) {
+			errs++
+			fmt.Printf("Error at 0x%x\n", k)
+			fmt.Printf("  Hash:  0x%x\n", got)
+			fmt.Printf("  Data:  0x%x\n", v)
+		}
+		if time.Since(lastLog) > 8*time.Second {
+			log.Info("Iterating the database", "at", fmt.Sprintf("%#x", k), "elapsed", common.PrettyDuration(time.Since(startTime)))
+			lastLog = time.Now()
+		}
+	}
+	if err := it.Error(); err != nil {
+		return err
+	}
+	log.Info("Iterated the state content", "errors", errs, "items", count)
+	return nil
+}
+
 func showLeveldbStats(db ethdb.KeyValueStater) {
 	if stats, err := db.Stat("leveldb.stats"); err != nil {
 		log.Warn("Failed to read database stats", "error", err)