summaryrefslogtreecommitdiff
path: root/xls_sheetpass_hash.cxx
blob: 02c7374382fbcc432ea08c2d06f71d2aab8e1b8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <vector>
#include <stdio.h>

using namespace std;

typedef unsigned char sal_uInt8;
typedef unsigned short sal_uInt16;

/* 
Reference: Office Open XML Part4 - Markup Language Reference, Section 
3.3.1.81 sheetProtection (Sheet Protection Options) 
 
Specifies the hash of the password required for editing this worksheet. This 
protection is optional and may be ignored by applications that choose not to 
support this functionality. The hash is generated from an 8-bit wide 
character. 16-bit Unicode characters must be converted down to 8 bits before 
the hash is computed, using the logic defined in the revisionsPassword 
attribute of §3.2.29. The resulting value is hashed using the algorithm 
defined below. 
 
[Note: An example algorithm to hash the user input into the value stored is 
as follows:
 
// Function Input:
//       szPassword: NULL terminated C-Style string
//       cchPassword: The number of characters in szPassword (not
including the NULL terminator)
WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) {
        WORD wPasswordHash;
        const CHAR *pch;
        wPasswordHash = 0;
        if (cchPassword > 0)
                {
                pch = &szPassword[cchPassword];
                while (pch-- != szPassword)
                         {
                         wPasswordHash = ((wPasswordHash >> 14) &
0x01) | ((wPasswordHash << 1) & 0x7fff);
                         wPasswordHash ^= *pch;
                         }
                wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
                }
        return(wPasswordHash);
}
 
end note] 
 
*/

sal_uInt16 getPasswordHash(const char* szPassword)
{
    sal_uInt16 cchPassword = strlen(szPassword);
    sal_uInt16 wPasswordHash = 0;
    if (!cchPassword)
        return wPasswordHash;

    const char* pch = &szPassword[cchPassword];
    while (pch-- != szPassword)
    {
        wPasswordHash = ((wPasswordHash >> 14) & 0x01) | 
                        ((wPasswordHash << 1) & 0x7fff);
        wPasswordHash ^= *pch;
    }

    wPasswordHash = ((wPasswordHash >> 14) & 0x01) | 
                    ((wPasswordHash << 1) & 0x7fff);

    wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
    wPasswordHash ^= cchPassword;

    return wPasswordHash;
}

int main (int argc, char** argv)
{
    if (argc < 2)
        exit(1);

    printf("input password = %s\n", argv[1]);
    sal_uInt16 hash = getPasswordHash(argv[1]);
    printf("hash = %4.4X\n", hash);

    return 0;
}