//
//  Functions needed for Windows Live ID support on MS Office sites
//
// Converts a string to a byte array, in ASCII format.
function StringToByteArrayASCII(str) {

  var i;
  var chArr = new Array();

  for (i=0; i<str.length; i++)
    chArr[i] = str.charCodeAt(i) & 0x7F;

  return chArr;
}

// Converts a string to a byte array, in Unicode format.
function StringToByteArrayUnicode(str) {

  var i;
  var chArr = new Array();

  for (i=0; i<str.length; i++) {
    var chCode = str.charCodeAt(i);
    chArr[i*2+1] = chCode>>>8;
    chArr[i*2] = chCode & 0xFF;
  }

  return chArr;
}

// Maps a byte to Base64 encoding.
function mapByteToBase64(ch) {

  if (ch>=0 && ch<26)
    return String.fromCharCode(65+ch);    // 65 is ASCII code for 'A'
  else if (ch>=26 && ch<52)
    return String.fromCharCode(97+ch-26); // 97 is ASCII code for 'a'
  else if (ch>=52 && ch<62)
    return String.fromCharCode(48+ch-52); // 48 is ASCII code for '0'
  else if (ch==62)
    return "+";
  else if (ch==63)
    return "/";
}

// Encodes a number in Base64 format, including
// zero-padding.
function Base64Encode(number, symcount) {

  var k, result = "";

  // This achieves the 0-padding effect
  for (k=symcount; k<4; k++)
    number = (number >> 6);

  for (k=0; k<symcount; k++) {
    result = mapByteToBase64(number & 0x3F) + result;  // Extract low-order 6 bits
    number = (number >> 6);                            // Right shift 6 bits
  }

  return result;
}

// Encodes a byte array in Base64 format, ensuring
// that the array is padded to meet 16-byte boundaries.
function ByteArrayToBase64(arg) {

  var len = arg.length;
  var result = "";      // String accumulating base64 encoding
  var i, j;             // Loop variables

  for (i=len-3; i>=0; i-=3) {
    var number = arg[i] | (arg[i+1] << 8) | (arg[i+2]<<16);
    result = result + Base64Encode(number, 4);
  }

  var remainder = len%3;

  var number = 0;
  for (i+=2; i>=0; i--)
    number = (number << 8) | arg[i];

  if (remainder==0)
    result = result + Base64Encode(number, 4);
  else if (remainder==1)
    result = result + Base64Encode(number << 16, 2) + "==";
  else if (remainder==2)
    result = result + Base64Encode(number << 8, 3) + "=";

  return result;
}

// Version of encryption used for credential string.
var EncryptionVersion = 0x01;
// Version of format for byte array used to construct credential string.
var FormatVersion = 0x02;

function EncryptedProperties(NewPassword, SA, OldPassword, MobilePin) {
  // Construct a credential string that can be used as the value of the
  // CipherValue element in the EncryptedProperties XML block.
  
  var inputArr = new Array();

  inputArr[0] = EncryptionVersion;
  inputArr[1] = FormatVersion;
  
  // Define a pointer into the byte array.
  i = 2;

  // Copy the length and characters of the new password (as ASCII)
  // into the byte array.
  var dataArray = StringToByteArrayASCII(NewPassword);
  inputArr[i++] = dataArray.length;
  for (j=0; j < dataArray.length; j++, i++) {
    inputArr[i] = dataArray[j];
  }

  // Copy the length and characters of the secret answer (as Unicode)
  // into the byte array.
  dataArray = StringToByteArrayUnicode(SA);
  inputArr[i++] = dataArray.length;
  for (j=0; j < dataArray.length; j++, i++) {
    inputArr[i] = dataArray[j];
  }

  // Copy the length and characters of the old password (as ASCII)
  // into the byte array.
  dataArray = StringToByteArrayASCII(OldPassword);
  inputArr[i++] = dataArray.length;
  for (j=0; j < dataArray.length; j++, i++) {
    inputArr[i] = dataArray[j];
  }

  // Copy the length and characters of the mobile PIN (as ASCII)
  // into the byte array.
  dataArray = StringToByteArrayASCII(MobilePin);
  inputArr[i++] = dataArray.length;
  for (j=0; j < dataArray.length; j++, i++) {
    inputArr[i] = dataArray[j];
  }

  // Encrypt and encode the byte array into a credential string
  
  // First, parse the RSA public key from the string representation.
  // The parseRSAKeyFromString() function is supplied by PPRSAEnc.js 
  // NOTE  The Key variable is supplied by JSPublicKey.srf
  var publicKey = parseRSAKeyFromString(Key);

  // Next, encrypt the byte array using the Windows Live public key.
  // NOTE  The randomNum variable is supplied by JSPublicKey.srf
  ciphertext = RSAencrypt(inputArr, publicKey, randomNum);

  // Finally, encode the returned encrypted text in Base64
  // and return the credential string for use in the CipherValue element.
  return ByteArrayToBase64(ciphertext);
}


