github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgRadius/MSCHAPV2/crypto.go (about) 1 package MSCHAPV2 2 3 import ( 4 "crypto" 5 _ "crypto/sha1" 6 7 _ "golang.org/x/crypto/md4" 8 ) 9 10 var generateAuthenticatorResponseMagic1 = []byte{0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 11 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 12 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 13 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74} 14 15 var generateAuthenticatorResponseMagic2 = []byte{0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 16 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 17 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 18 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 19 0x6E} 20 21 // RFC2759 section 8.7 page 9 22 // return binary form of the result 23 // in the hash example password is utf-16 encode. 24 // Password = "clientPass" 密码的输入格式比较奇怪.utf16? 25 // = 63 00 6C 00 69 00 65 00 6E 00 26 // 74 00 50 00 61 00 73 00 73 00 27 func GenerateAuthenticatorResponse(Password []byte, NTResponse [24]byte, PeerChallenge [16]byte, 28 AuthenticatorChallenge [16]byte, UserName []byte) [20]byte { 29 //TODO 解决中文密码的问题 30 utf16Password := make([]byte, len(Password)*2) 31 for i := range Password { 32 utf16Password[i*2] = Password[i] 33 } 34 /* 35 * Hash the password with MD4 36 */ 37 38 PasswordHash := md4(utf16Password) //ntPasswordHash 39 40 /* 41 * Now hash the hash 42 */ 43 44 PasswordHashHash := md4(PasswordHash) //hashNtPasswordHash 45 46 h := crypto.SHA1.New() 47 h.Write(PasswordHashHash) 48 h.Write(NTResponse[:]) 49 h.Write(generateAuthenticatorResponseMagic1) 50 Digest := h.Sum(nil) 51 52 Challenge := challengeHash(PeerChallenge, AuthenticatorChallenge, UserName) 53 54 h = crypto.SHA1.New() 55 h.Write(Digest) 56 h.Write(Challenge) 57 h.Write(generateAuthenticatorResponseMagic2) 58 Digest = h.Sum(nil) 59 60 out := [20]byte{} 61 copy(out[:], Digest) 62 return out 63 } 64 65 // it is md4 hash 66 func md4(Password []byte) []byte { 67 h := crypto.MD4.New() 68 h.Write(Password) 69 return h.Sum(nil) 70 } 71 72 func challengeHash(PeerChallenge [16]byte, AuthenticatorChallenge [16]byte, UserName []byte) []byte { 73 h := crypto.SHA1.New() 74 h.Write(PeerChallenge[:]) 75 h.Write(AuthenticatorChallenge[:]) 76 h.Write(UserName) 77 Digest := h.Sum(nil) 78 79 Challenge := make([]byte, 8) 80 copy(Challenge, Digest[:8]) 81 return Challenge 82 } 83 84 var msCHAPV2GetSendAndRecvKeySHSpad1 = [40]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 88 89 var msCHAPV2GetSendAndRecvKeySHSpad2 = [40]byte{0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 90 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 91 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 92 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2} 93 94 var msCHAPV2GetSendAndRecvKeyMagic1 = [27]byte{0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 95 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 96 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79} 97 98 var msCHAPV2GetSendAndRecvKeyMagic2 = [84]byte{0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 99 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 100 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 101 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 102 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 103 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 104 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 105 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 106 0x6b, 0x65, 0x79, 0x2e} 107 108 var msCHAPV2GetSendAndRecvKeyMagic3 = [84]byte{0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 109 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 110 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 111 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 112 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 113 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 114 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 115 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 116 0x6b, 0x65, 0x79, 0x2e} 117 118 func msCHAPV2GetSendAndRecvKeyGetMasterKey(passwordHashHash []byte, NTResponse [24]byte) (masterkey [16]byte) { 119 // Secure Hash Standard Federal Information Processing Standards Publication 180-1 -> SHA1 120 h := crypto.SHA1.New() 121 h.Write(passwordHashHash) 122 h.Write(NTResponse[:]) 123 h.Write(msCHAPV2GetSendAndRecvKeyMagic1[:]) 124 Digest := h.Sum(nil) 125 copy(masterkey[:], Digest[:16]) 126 return 127 } 128 129 func msCHAPV2GetSendAndRecvKeyGetAsymetricStartKey(masterkey [16]byte, sessionKeyLength int, IsSend bool, IsServer bool) (sessionKey []byte) { 130 var s [84]byte 131 if IsSend { 132 if IsServer { 133 s = msCHAPV2GetSendAndRecvKeyMagic3 134 } else { 135 s = msCHAPV2GetSendAndRecvKeyMagic2 136 } 137 } else { 138 if IsServer { 139 s = msCHAPV2GetSendAndRecvKeyMagic2 140 } else { 141 s = msCHAPV2GetSendAndRecvKeyMagic3 142 } 143 } 144 h := crypto.SHA1.New() 145 h.Write(masterkey[:]) 146 h.Write(msCHAPV2GetSendAndRecvKeySHSpad1[:]) 147 h.Write(s[:]) 148 h.Write(msCHAPV2GetSendAndRecvKeySHSpad2[:]) 149 Digest := h.Sum(nil) 150 sessionKey = Digest[:sessionKeyLength] 151 return sessionKey 152 } 153 154 // http://www.ietf.org/rfc/rfc3079.txt 155 // Password = "clientPass" 密码的输入格式已经修正 156 // = 63 00 6C 00 69 00 65 00 6E 00 157 // 74 00 50 00 61 00 73 00 73 00 158 func MsCHAPV2GetSendAndRecvKey(Password []byte, NTResponse [24]byte) (sendKey []byte, recvKey []byte) { 159 //TODO 解决中文密码的问题 160 utf16Password := make([]byte, len(Password)*2) 161 for i := range Password { 162 utf16Password[i*2] = Password[i] 163 } 164 PasswordHash := md4(utf16Password) 165 PasswordHashHash := md4(PasswordHash) 166 167 masterKey := msCHAPV2GetSendAndRecvKeyGetMasterKey(PasswordHashHash, NTResponse) 168 MasterSendKey := msCHAPV2GetSendAndRecvKeyGetAsymetricStartKey(masterKey, 16, true, true) 169 MasterReceiveKey := msCHAPV2GetSendAndRecvKeyGetAsymetricStartKey(masterKey, 16, false, true) 170 171 return MasterSendKey, MasterReceiveKey 172 }