From 4dbc78ce0a0d40be189b4c77207cdbb598846c73 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 2 Nov 2018 23:08:31 +0800 Subject: resolve #273 new feature: protect sheet support new feature: protect sheet support, relate issue #273 --- lib.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'lib.go') diff --git a/lib.go b/lib.go index 8e63da9..cf43dc9 100644 --- a/lib.go +++ b/lib.go @@ -15,6 +15,8 @@ import ( "io" "log" "math" + "strconv" + "strings" "unicode" ) @@ -199,3 +201,29 @@ func namespaceStrictToTransitional(content []byte) []byte { } return content } + +// genSheetPasswd provides a method to generate password for worksheet +// protection by given plaintext. When an Excel sheet is being protected with +// a password, a 16-bit (two byte) long hash is generated. To verify a +// password, it is compared to the hash. Obviously, if the input data volume +// is great, numerous passwords will match the same hash. Here is the +// algorithm to create the hash value: +// +// take the ASCII values of all characters shift left the first character 1 bit, the second 2 bits and so on (use only the lower 15 bits and rotate all higher bits, the highest bit of the 16-bit value is always 0 [signed short]) +// XOR all these values +// XOR the count of characters +// XOR the constant 0xCE4B +func genSheetPasswd(plaintext string) string { + var password int64 = 0x0000 + var charPos uint = 1 + for _, v := range plaintext { + value := int64(v) << charPos + charPos++ + rotatedBits := value >> 15 // rotated bits beyond bit 15 + value &= 0x7fff // first 15 bits + password ^= (value | rotatedBits) + } + password ^= int64(len(plaintext)) + password ^= 0xCE4B + return strings.ToUpper(strconv.FormatInt(password, 16)) +} -- cgit v1.2.1