github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/upstreamproxy/go-ntlm/ntlm/crypto.go (about) 1 //Copyright 2013 Thomson Reuters Global Resources. BSD License please see License file for more information 2 3 package ntlm 4 5 import ( 6 desP "crypto/des" 7 hmacP "crypto/hmac" 8 md5P "crypto/md5" 9 "crypto/rand" 10 rc4P "crypto/rc4" 11 md4P "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/upstreamproxy/go-ntlm/ntlm/md4" 12 crc32P "hash/crc32" 13 ) 14 15 func md4(data []byte) []byte { 16 md4 := md4P.New() 17 md4.Write(data) 18 return md4.Sum(nil) 19 } 20 21 func md5(data []byte) []byte { 22 md5 := md5P.New() 23 md5.Write(data) 24 return md5.Sum(nil) 25 } 26 27 // Indicates the computation of a 16-byte HMAC-keyed MD5 message digest of the byte string M using the key K. 28 func hmacMd5(key []byte, data []byte) []byte { 29 mac := hmacP.New(md5P.New, key) 30 mac.Write(data) 31 return mac.Sum(nil) 32 } 33 34 // Indicates the computation of an N-byte cryptographic- strength random number. 35 func nonce(length int) []byte { 36 result := make([]byte, length) 37 rand.Read(result) 38 return result 39 } 40 41 func crc32(bytes []byte) uint32 { 42 crc := crc32P.New(crc32P.IEEETable) 43 crc.Write(bytes) 44 return crc.Sum32() 45 } 46 47 // Indicates the encryption of data item D with the key K using the RC4 algorithm. 48 func rc4K(key []byte, ciphertext []byte) ([]byte, error) { 49 cipher, err := rc4P.NewCipher(key) 50 if err != nil { 51 return nil, err 52 } 53 result := make([]byte, len(ciphertext)) 54 cipher.XORKeyStream(result, ciphertext) 55 return result, nil 56 } 57 58 func rc4Init(key []byte) (cipher *rc4P.Cipher, err error) { 59 cipher, err = rc4P.NewCipher(key) 60 if err != nil { 61 return nil, err 62 } 63 return cipher, nil 64 } 65 66 func rc4(cipher *rc4P.Cipher, ciphertext []byte) []byte { 67 result := make([]byte, len(ciphertext)) 68 cipher.XORKeyStream(result, ciphertext) 69 return result 70 } 71 72 // Indicates the encryption of an 8-byte data item D with the 7-byte key K using the Data Encryption Standard (DES) 73 // algorithm in Electronic Codebook (ECB) mode. The result is 8 bytes in length ([FIPS46-2]). 74 func des(key []byte, ciphertext []byte) ([]byte, error) { 75 calcKey := createDesKey(key) 76 cipher, err := desP.NewCipher(calcKey) 77 if err != nil { 78 return nil, err 79 } 80 81 result := make([]byte, len(ciphertext)) 82 cipher.Encrypt(result, ciphertext) 83 84 return result, nil 85 } 86 87 // Indicates the encryption of an 8-byte data item D with the 16-byte key K using the Data Encryption Standard Long (DESL) algorithm. 88 // The result is 24 bytes in length. DESL(K, D) is computed as follows. 89 // Note K[] implies a key represented as a character array. 90 func desL(key []byte, cipherText []byte) ([]byte, error) { 91 out1, err := des(zeroPaddedBytes(key, 0, 7), cipherText) 92 if err != nil { 93 return nil, err 94 } 95 96 out2, err := des(zeroPaddedBytes(key, 7, 7), cipherText) 97 if err != nil { 98 return nil, err 99 } 100 101 out3, err := des(zeroPaddedBytes(key, 14, 7), cipherText) 102 if err != nil { 103 return nil, err 104 } 105 106 return concat(out1, out2, out3), nil 107 } 108 109 // Creates a DES encryption key from the given 7 byte key material. 110 func createDesKey(keyBytes []byte) []byte { 111 material := zeroBytes(8) 112 material[0] = keyBytes[0] 113 material[1] = (byte)(keyBytes[0]<<7 | (keyBytes[1]&0xff)>>1) 114 material[2] = (byte)(keyBytes[1]<<6 | (keyBytes[2]&0xff)>>2) 115 material[3] = (byte)(keyBytes[2]<<5 | (keyBytes[3]&0xff)>>3) 116 material[4] = (byte)(keyBytes[3]<<4 | (keyBytes[4]&0xff)>>4) 117 material[5] = (byte)(keyBytes[4]<<3 | (keyBytes[5]&0xff)>>5) 118 material[6] = (byte)(keyBytes[5]<<2 | (keyBytes[6]&0xff)>>6) 119 material[7] = (byte)(keyBytes[6] << 1) 120 oddParity(material) 121 return material 122 } 123 124 // Applies odd parity to the given byte array. 125 func oddParity(bytes []byte) { 126 for i := 0; i < len(bytes); i++ { 127 b := bytes[i] 128 needsParity := (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ (b >> 1)) & 0x01) == 0 129 if needsParity { 130 bytes[i] = bytes[i] | byte(0x01) 131 } else { 132 bytes[i] = bytes[i] & byte(0xfe) 133 } 134 } 135 }