-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use a hash to detect changes to Certificate resource.
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
- Loading branch information
Showing
16 changed files
with
1,391 additions
and
303 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# infohash | ||
|
||
A hash & comparator that tells you why the hash did not match. | ||
|
||
For example if you edit the Name field in a struct, this library will tell | ||
you that the hash did not match because the Name field was changed. | ||
|
||
## Space Complexity | ||
|
||
Per struct, we store a "global" hash and a "local" hash for each field. | ||
The global hash is 64 bits long, and the local hashes are 32 bits long. | ||
We use hamming codes to detect which "local" hash has changed. This requires | ||
us to store log2(nr_fields+1) 32 bit parity hashes instead of nr_fields 32 bit | ||
hashes. The total space complexity is therefore: | ||
|
||
``` | ||
64 + log2(nr_fields+1) * 32 bits | ||
= 8 + log2(nr_fields+1) * 4 bytes | ||
= 16 + log2(nr_fields+1) * 8 hex characters | ||
``` | ||
|
||
As a rule of thumb, this library is only useful if you have at least +-7 fields, | ||
otherwise you can just store the hashes of each field individually. | ||
|
||
## Safety | ||
|
||
This library will detect any changes to the struct (with collision chance of 1/2^32, accounting for birthday attack). | ||
However, accurately detecting which field changed is only possible if only one field changed. | ||
If multiple fields changed, we can only detect that at least one field changed, but not which one. | ||
This is because we use hamming codes to detect which field changed, and hamming codes can only detect | ||
single field errors. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
Copyright 2020 The cert-manager Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package infohash | ||
|
||
func calculateHammingCode(fields []uint32) []uint32 { | ||
log2NumberOfFieldsPlusOne := log2OfXPlusOne(uint32(len(fields))) | ||
parityCodes := make([]uint32, log2NumberOfFieldsPlusOne) | ||
|
||
for id, field := range fields { | ||
for i := range parityCodes { | ||
if (id+1)&(1<<i) != 0 { | ||
parityCodes[i] ^= field | ||
} | ||
} | ||
} | ||
|
||
return parityCodes | ||
} | ||
|
||
func findErrorLocation(fields []uint32, hammingCode []uint32) (bool, uint32) { | ||
expectedCode := calculateHammingCode(fields) | ||
var errorLocation uint32 | ||
|
||
for i := range hammingCode { | ||
if hammingCode[i] != expectedCode[i] { | ||
errorLocation |= 1 << i | ||
} | ||
} | ||
|
||
if errorLocation == 0 || errorLocation > uint32(len(fields)) { | ||
return false, 0 | ||
} | ||
|
||
return true, errorLocation - 1 | ||
} | ||
|
||
func log2OfXPlusOne(x uint32) uint32 { | ||
var r uint32 | ||
for x > 0 { | ||
x >>= 1 | ||
r += 1 | ||
} | ||
return r | ||
} |
Oops, something went wrong.