diff options
Diffstat (limited to 'crypt.go')
-rw-r--r-- | crypt.go | 64 |
1 files changed, 55 insertions, 9 deletions
@@ -43,6 +43,7 @@ var ( packageOffset = 8 // First 8 bytes are the size of the stream packageEncryptionChunkSize = 4096 iterCount = 50000 + sheetProtectionSpinCount = 1e5 oleIdentifier = []byte{ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1, } @@ -146,7 +147,7 @@ func Decrypt(raw []byte, opt *Options) (packageBuf []byte, err error) { case "standard": return standardDecrypt(encryptionInfoBuf, encryptedPackageBuf, opt) default: - err = ErrUnsupportEncryptMechanism + err = ErrUnsupportedEncryptMechanism } return } @@ -307,7 +308,7 @@ func encryptionMechanism(buffer []byte) (mechanism string, err error) { } else if (versionMajor == 3 || versionMajor == 4) && versionMinor == 3 { mechanism = "extensible" } - err = ErrUnsupportEncryptMechanism + err = ErrUnsupportedEncryptMechanism return } @@ -387,14 +388,14 @@ func standardConvertPasswdToKey(header StandardEncryptionHeader, verifier Standa key = hashing("sha1", iterator, key) } var block int - hfinal := hashing("sha1", key, createUInt32LEBuffer(block, 4)) + hFinal := hashing("sha1", key, createUInt32LEBuffer(block, 4)) cbRequiredKeyLength := int(header.KeySize) / 8 cbHash := sha1.Size buf1 := bytes.Repeat([]byte{0x36}, 64) - buf1 = append(standardXORBytes(hfinal, buf1[:cbHash]), buf1[cbHash:]...) + buf1 = append(standardXORBytes(hFinal, buf1[:cbHash]), buf1[cbHash:]...) x1 := hashing("sha1", buf1) buf2 := bytes.Repeat([]byte{0x5c}, 64) - buf2 = append(standardXORBytes(hfinal, buf2[:cbHash]), buf2[cbHash:]...) + buf2 = append(standardXORBytes(hFinal, buf2[:cbHash]), buf2[cbHash:]...) x2 := hashing("sha1", buf2) x3 := append(x1, x2...) keyDerived := x3[:cbRequiredKeyLength] @@ -417,7 +418,8 @@ func standardXORBytes(a, b []byte) []byte { // ECMA-376 Agile Encryption // agileDecrypt decrypt the CFB file format with ECMA-376 agile encryption. -// Support cryptographic algorithm: MD4, MD5, RIPEMD-160, SHA1, SHA256, SHA384 and SHA512. +// Support cryptographic algorithm: MD4, MD5, RIPEMD-160, SHA1, SHA256, +// SHA384 and SHA512. func agileDecrypt(encryptionInfoBuf, encryptedPackageBuf []byte, opt *Options) (packageBuf []byte, err error) { var encryptionInfo Encryption if encryptionInfo, err = parseEncryptionInfo(encryptionInfoBuf[8:]); err != nil { @@ -605,11 +607,55 @@ func createIV(blockKey interface{}, encryption Encryption) ([]byte, error) { return iv, nil } -// randomBytes returns securely generated random bytes. It will return an error if the system's -// secure random number generator fails to function correctly, in which case the caller should not -// continue. +// randomBytes returns securely generated random bytes. It will return an +// error if the system's secure random number generator fails to function +// correctly, in which case the caller should not continue. func randomBytes(n int) ([]byte, error) { b := make([]byte, n) _, err := rand.Read(b) return b, err } + +// ISO Write Protection Method + +// genISOPasswdHash implements the ISO password hashing algorithm by given +// plaintext password, name of the cryptographic hash algorithm, salt value +// and spin count. +func genISOPasswdHash(passwd, hashAlgorithm, salt string, spinCount int) (hashValue, saltValue string, err error) { + if len(passwd) < 1 || len(passwd) > MaxFieldLength { + err = ErrPasswordLengthInvalid + return + } + hash, ok := map[string]string{ + "MD4": "md4", + "MD5": "md5", + "SHA-1": "sha1", + "SHA-256": "sha256", + "SHA-384": "sha384", + "SHA-512": "sha512", + }[hashAlgorithm] + if !ok { + err = ErrUnsupportedHashAlgorithm + return + } + var b bytes.Buffer + s, _ := randomBytes(16) + if salt != "" { + if s, err = base64.StdEncoding.DecodeString(salt); err != nil { + return + } + } + b.Write(s) + encoder := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewEncoder() + passwordBuffer, _ := encoder.Bytes([]byte(passwd)) + b.Write(passwordBuffer) + // Generate the initial hash. + key := hashing(hash, b.Bytes()) + // Now regenerate until spin count. + for i := 0; i < spinCount; i++ { + iterator := createUInt32LEBuffer(i, 4) + key = hashing(hash, key, iterator) + } + hashValue, saltValue = base64.StdEncoding.EncodeToString(key), base64.StdEncoding.EncodeToString(s) + return +} |