I am trying to get the MS-MPPE-Send-key and MS-MPPE-Recv-key from the MS-CHAPv2 challenge material. I am able to follow the RFCs 2548 3078 and 3079 to the step of getting the GetNewKeyFromSHA() it is 16 bytes long.

I can use the key to encrypt data as the example in 3079. The problem is that I am not sure what should I do to get the session keys used in the RFC 2548 to get MS-MPPE-Send-key and MS-MPPE-Recv-key fields from there.

I have an example of freeradius and the session key is converted from 16 bytes long to 32 bytes long before the construction of the string stated in RFC 2548.

I have tried to encrypt with RC4 the session keys after GetNewKeyFromSHA() but it is not working for me. If someone could explain a bit in detail this intermediate step it would be nice!

Edit 1

I also have tried to make the encryption in 2548 twice but still no results, I am now digging into the freeRADIUS source code but it is not easy to follow after getting the master key from the MS-CHAPv2 material. Any ideas?

Edit 2

Looking into freeradius it seems to be that firstly it derives the keys from the MS-CHAv2 material but then instead of encrypt an send them, it uses the master secret and the random numbers from the TLS handshake to produce the 32 bytes Send and Receive keys. This is as RFC 2716 says, then encrypts them as RFC 2548 and finally it sends them.

So is it possible to use the master key derived from the MS-CHAPv2 material as in the RFC 3079? or the only way to do this is as freeradius does?

  • 1
    You're throwing around a lot of RFCs. Can you give a step by step of how you think the derivation should go, and how you see it being performed by freeradius? Also, can you be specific about which sections in the RFCs you're referencing?
    – RoraΖ
    Commented Jul 6, 2015 at 18:13

1 Answer 1


Not sure of your question, is it how these values are encrypted? It is described in RFC-2548 section 2.4.2.

The reason I think this is that in your question you state:

I have an example of freeradius and the session key is converted from 16 bytes long to 32 bytes long before the construction of the string stated in RFC 2548.

so you are wondering how you go from your 16-byte key to the 32-byte value used in the RADIUS attribute?

Basically your 32-byte key is 2 catenated MD5 hashes of your 16-byte key. The value must be a multiple of 16 for this reason. The reason that you have 32, rather than 16 is that you prepend a single-byte value 16 (for key-length) onto the key value which makes the length 17 and thus pushes it into a second 16-byte window. The remaining 15 bytes should be 0-padded.

So anyway you're ciphering your now 17-byte key-value using the RADIUS shared-secret, the 16-byte Request Authenticator from the original RADIUS request, and a random 2-byte salt value.

The random salt value can literally be anything. As you've noted freeradius derives this from a TLS function but that's only suitable where you're tunneling over TLS really. You can just pull something out of the air.

Then you prepend the two byte salt value onto your 32-byte encrypted value, to make a 34-byte value and you're done!

     Construct a plaintext version of the String field by concate-
     nating the Key-Length and Key sub-fields.  If necessary, pad
     the resulting string until its length (in octets) is an even
     multiple of 16.  It is recommended that zero octets (0x00) be
     used for padding.  Call this plaintext P.

     Call the shared secret S, the pseudo-random 128-bit Request
     Authenticator (from the corresponding Access-Request packet) R,
     and the contents of the Salt field A.  Break P into 16 octet
     chunks p(1), p(2)...p(i), where i = len(P)/16.  Call the
     ciphertext blocks c(1), c(2)...c(i) and the final ciphertext C.
     Intermediate values b(1), b(2)...c(i) are required.  Encryption
     is performed in the following manner ('+' indicates

  b(1) = MD5(S + R + A)    c(1) = p(1) xor b(1)   C = c(1)
  b(2) = MD5(S + c(1))     c(2) = p(2) xor b(2)   C = C + c(2)
              .                      .
              .                      .
              .                      .
  b(i) = MD5(S + c(i-1))   c(i) = p(i) xor b(i)   C = C + c(i)

  The   resulting   encrypted   String   field    will    contain

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .