# Checksum/Hash on a group of OPC UA Tags

**URL:** <https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576>\
**Category:** Ignition\
**Tags:** ignition81, database, scripting\
**Created:** [April 25, 2025, 4:24pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576 "2025-04-25T16:24:42Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jacob.leonard](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jacob.leonard](https://forum.inductiveautomation.com/u/jacob.leonard)\
**Post date:** [April 25, 2025, 4:24pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/1 "2025-04-25T16:24:42Z")

</div>

TLDR:  
I have a UDT that I am using to write/read recipes for a process we run. Each part we make has its own recipe, and they have been manually confirming that the recipe matches our documented recipes. This has led to errors and scraped out parts. And it is surprisingly difficulted to maintain change management across 7 machines.

I would love to have some kind of checksum to compare rather than just checking by a bunch of if-then statements.

I know that Ignition has a lot of java libs built into it and callable in a script. Could one of them have a checksum or hashing ability?

---

<div class="post-metadata">

**Author:** ![jacob.leonard](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jacob.leonard](https://forum.inductiveautomation.com/u/jacob.leonard)\
**Post date:** [April 25, 2025, 4:33pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/2 "2025-04-25T16:33:17Z")

</div>

```python
import org.apache.commons.codec.digest.DigestUtils.sha256Hex as sha256Hex

data = "example-data-structure"
print(sha256Hex(data))

```

ChatGPT for the win  
But it only works on strings

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [April 25, 2025, 5:20pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/3 "2025-04-25T17:20:21Z")

</div>

If the tags are all either strings or numbers, they should be hashable.

So in theory you should be able to iterate through the master recipe, and the selected recipe, and compare the results of the python builtin `hash()` function. Something like this:

```python
def chunker(seq,size):
	return (seq[pos:pos + size] for pos in xrange(0,len(seq),size))
	
def confirmRecipe():
	documnetedPaths = ["list.of.paths.to.documented.values"]
	selectedPaths = ["list.of.paths.to.selected.values"]
	tagPaths = documentedPaths + selectedPaths
	tagValues = system.tag.readBlocking(tagPaths)
	
	documentedValues, selectedValues = [[qv.value for qv in chunk] for chunk in chunker(tagValues,len(documentedPaths))]
	
	for i, value in enumerate(documentedValues):
		if hash(value) != hash(selectedValues[i]):
			#flag as unconfirmed
			return False
	
	#if execution makes it here then recipes match
	return True

```

This will work with `str`,`int`,`bool`, `float`

Or any other type that is hashable.

---

<div class="post-metadata">

**Author:** ![jacob.leonard](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jacob.leonard](https://forum.inductiveautomation.com/u/jacob.leonard)\
**Post date:** [April 25, 2025, 5:44pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/4 "2025-04-25T17:44:26Z")

</div>

```python
import org.apache.commons.codec.digest.DigestUtils.sha256Hex as sha256Hex

segmentTagPath = ["[default]Folder/Tag_A","[default]Folder/Tag_B"]
values = system.tag.readBlocking(segmentTagPath)
valueList = ''
for x in values:
    valueList + str(x.value)
print(sha256Hex(valueList))

```

I ended up doing something like this. The main thing is the sha256Hex function only works on strings.

So, I index into the returning array of data and pulled only the value of the tag, and nothing else as that will affect the hash. And stringify the value.

Concatenate all the values into a string and run the sha256Hex function on that.

Note: Any change of the order of the tags read will affect the hash amount.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [April 25, 2025, 6:03pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/5 "2025-04-25T18:03:32Z")

</div>

We use [`DigestBuilder`](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.47/com/inductiveautomation/ignition/common/util/DigestBuilder.html) for this sort of task internally.

So your snippet becomes:

```python
from com.inductiveautomation.ignition.common.util import DigestBuilder

segmentTagPath = ["[default]Folder/Tag_A","[default]Folder/Tag_B"]
values = system.tag.readBlocking(segmentTagPath)
digest = DigestBuilder.sha256()
for x in values:
    digest.update(x.value)
print(digest.buildHexString())

```

The big advantage being the `update` function has overloads for common numeric types as well as direct byte arrays.

---

<div class="post-metadata">

**Author:** ![jacob.leonard](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jacob.leonard](https://forum.inductiveautomation.com/u/jacob.leonard)\
**Post date:** [April 30, 2025, 4:06pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/6 "2025-04-30T16:06:23Z")

</div>

I think that PDriffith solution will work and thus he gets the solution point. Altho i might just use 16 bits to keep it short.

But then I started to wonder if sha256 was the absolute best function to use.

I went down a rabbit hole. Not knowing too much about cryptography, it took me some time to describe the things I want in a function:

**Avalanche Effect:** I would like it to have a drastic change if even one datapoint is off . That way operators can very easily tell if the settings are off

**Short:** I would like it to be less than 32 characters so we can have operators check, by hand, it to our documented procedure

**Ease of Implementation:** Something someone already has a lib for would be great

**Reversible:** I would like it to be uncompressible to see the data inside if possible

**Can Be Insecure:** No need for keys or security

I don't expect there to be a function/algorithm that matches all these criteria but you never know untill you ask

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [April 30, 2025, 5:22pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/7 "2025-04-30T17:22:44Z")

</div>

Short and reversible are literally mutually incompatible.

Also, short increases the risk of collisions significantly.

You may be interested in sidestepping the problem:

> [@Tag Version Control Module](https://forum.inductiveautomation.com/t/tag-version-control-module/104022):
>
> Hello All, A while back I published (A bit quietly) a module that could enable some better version control of tags, and I am not sure if I ever published it here. So I figured I would share it for all of those that will not have access to 8.3 for some time! Currently it supports the following features: Allows REST endpoints that can do tag imports/exports/edits based off of provided JSON content. Adds the ability to auto-import tags based off of a config file located in the gateways data dir…

---

<div class="post-metadata">

**Author:** ![Leor\_Fishman](https://avatars.discourse-cdn.com/v4/letter/l/e19adc/32.png) [@Leor\_Fishman](https://forum.inductiveautomation.com/u/Leor_Fishman)\
**Post date:** [April 30, 2025, 8:16pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/8 "2025-04-30T20:16:28Z")

</div>

unfortunately, [Pigeonhole principle - Wikipedia](https://en.wikipedia.org/wiki/Pigeonhole_principle) causes you suffering.

What you _could_ do is 'reversible compression, but operators check the first 6 bits of the hash', git style

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 30, 2026, 4:29pm UTC](https://forum.inductiveautomation.com/t/checksum-hash-on-a-group-of-opc-ua-tags/105576/9 "2026-01-30T16:29:15Z")

</div>

Split this topic on January 30, 2026, 4:29pm UTC

A post was split to a new topic: [Question about offline installation](https://forum.inductiveautomation.com/t/question-about-offline-installation/113663)
