code: def radius_encrypt_keys(plain_text, secret, request_authenticator, salt):
      
      i = len(plain_text) / 16
      b = hashlib.new("md5", secret + request_authenticator + salt).digest()
      c = xor(plain_text[:16], b)
      result = c
      for x in range(1, i):
          b = hashlib.new("md5", secret + c).digest()
          c = xor(plain_text[x * 16:(x + 1) * 16], b)
          result += c
      return result
docs: 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
           concatenation):
  
        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
        c(1)+c(2)+...+c(i).