/// <summary> /// Extracts the userId from a string built by UserIdToTimestampedUserId() /// </summary> /// <param name="text">String originally encripted by UserIdToTimestampedUserId()</param> /// <param name="minAllowedTime">Limit time-to-live of the timestamped string. UTC</param> /// <param name="defaultValue">If a non-null value is passed, fail silently and return it. Otherwise throw.</param> /// <returns>The original UserId. It may be 0 on error, depending on defaultValue</returns> public static int TimestampedUserIdToUserId(string text, DateTime minAllowedTime, int?defaultValue = 0) { try { if (String.IsNullOrWhiteSpace(text)) { throw new ArgumentNullException(); } var extTimeText = text.Substring(0, 16); var binTime = Int64.Parse(extTimeText, NumberStyles.HexNumber); var time = DateTime.FromBinary(binTime); if (time < minAllowedTime) { throw new Exception("Timestamp is too old"); } var extEncriptedUserIdText = text.Substring(16, 8); var key = extTimeText.Substring(6, 10).ToLower(); var userId = Skip32Utils.DecriptHexStringToInt(extEncriptedUserIdText, key, null); var userIdText = userId.ToString("X"); var textToHash = (extTimeText + userIdText).ToLower() + PayPalUserIdHashSalt; var bytesToHash = System.Text.Encoding.UTF8.GetBytes(textToHash); var hash = System.Security.Cryptography.MD5.Create().ComputeHash(bytesToHash); var hashText = new Guid(hash).ToString("N"); var extHashText = text.Substring(24, 32); if (extHashText.ToLower() != hashText.ToLower()) { throw new Exception("Hash does not match."); } return(userId); } catch { if (defaultValue.HasValue) { // Fail silently. return(defaultValue.Value); } else { throw; } } }
/// <summary> /// Protect userId from tampering with when sending form data to PayPal. /// </summary> public static string UserIdToTimestampedUserId(int userId, DateTime time) { var timeText = time.ToBinary().ToString("X"); // 16 chars, the last gigits change faster. var userIdText = userId.ToString("X"); // 8 chars var textToHash = (timeText + userIdText).ToLower() + PayPalUserIdHashSalt; var bytesToHash = System.Text.Encoding.UTF8.GetBytes(textToHash); var hash = System.Security.Cryptography.MD5.Create().ComputeHash(bytesToHash); var hashText = new Guid(hash).ToString("N"); // 32 chars lower-case var key = timeText.Substring(6, 10).ToLower(); var encriptedUserIdText = Skip32Utils.EncriptIntToHexString(userId, key); return((timeText + encriptedUserIdText + hashText).ToLower()); // 16 + 8 + 32 = 56 chars //var chunkSize = 24; //// 49 chars = 2 chunks * 24 chars + 1 separating space. //var chunkedText = string.Join(" ", Enumerable.Range(0, text.Length / chunkSize).Select(i => text.Substring(i * chunkSize, chunkSize))); //return chunkedText; }