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  }