public override string Encode(string siteName, SiteType siteType, uint siteCounter, SiteVariant siteVariant, string siteContext = null) { if (siteCounter == 0) { siteCounter = (uint)(CurrentTimeMillis() / (300 * 1000)) * 300; } var siteScope = SiteVariantHelper.GetScope(siteVariant); var siteNameBytes = Encoding.UTF8.GetBytes(siteName); var siteNameLengthBytes = BytesForInt(siteName.Length); var siteCounterBytes = BytesForInt(siteCounter); var siteContextBytes = string.IsNullOrEmpty(siteContext) ? null : Encoding.UTF8.GetBytes(siteContext); var siteContextLengthBytes = BytesForInt(siteContextBytes?.Length ?? 0); var sitePasswordInfo = Concat(Encoding.UTF8.GetBytes(siteScope), siteNameLengthBytes, siteNameBytes, siteCounterBytes); if (siteContextBytes != null) { sitePasswordInfo = Concat(sitePasswordInfo, siteContextLengthBytes, siteContextBytes); } var sitePasswordSeed = ComputeHmacOf(MasterKeyBytes, sitePasswordInfo); var templateIndex = sitePasswordSeed[0] & 0xFF; // Mask the integer's sign. var template = SiteTypeHelper.GetTemplateAtRollingIndex(siteType, templateIndex); var password = new StringBuilder(template.TemplateString.Length); for (var i = 0; i < template.TemplateString.Length; ++i) { var characterIndex = sitePasswordSeed[i + 1] & 0xFF; // Mask the integer's sign. var characterClass = template.TemplateChars[i]; var passwordCharacter = TemplateCharacterClassHelper.GetCharacterAtRollingIndex(characterClass, characterIndex); password.Append(passwordCharacter); } return(password.ToString()); }
public override string Encode(string siteName, SiteType siteType, uint siteCounter, SiteVariant siteVariant, string siteContext = null) { if (siteCounter == 0) { siteCounter = (uint)(CurrentTimeMillis() / (300 * 1000)) * 300; } var siteScope = SiteVariantHelper.GetScope(siteVariant); var siteNameBytes = Encoding.UTF8.GetBytes(siteName); var siteNameLengthBytes = BytesForInt(siteName.Length); var siteCounterBytes = BytesForInt(siteCounter); var siteContextBytes = string.IsNullOrEmpty(siteContext) ? null : Encoding.UTF8.GetBytes(siteContext); var siteContextLengthBytes = BytesForInt(siteContextBytes?.Length ?? 0); var sitePasswordInfo = Concat(Encoding.UTF8.GetBytes(siteScope), siteNameLengthBytes, siteNameBytes, siteCounterBytes); if (siteContextBytes != null) { sitePasswordInfo = Concat(sitePasswordInfo, siteContextLengthBytes, siteContextBytes); } var sitePasswordSeedBytes = ComputeHmacOf(MasterKeyBytes, sitePasswordInfo); var sitePasswordSeed = new int[sitePasswordSeedBytes.Length]; for (var i = 0; i < sitePasswordSeedBytes.Length; ++i) { var m = new MemoryStream(sizeof(int) / sizeof(byte)); m.SetLength(sizeof(int) / sizeof(byte)); Fill(m, (sbyte)sitePasswordSeedBytes[i] > 0 ? (byte)0x00 : (byte)0xFF); var w = new BinaryWriter(m); { w.Seek(2, SeekOrigin.Begin); w.Write(sitePasswordSeedBytes[i]); w.Flush(); m.Position = 0; } // change byte order m = new MemoryStream(ChangeByteOrder(m.ToArray(), ByteOrder.BigEndian)); using (var r = new BinaryReader(m)) { sitePasswordSeed[i] = r.ReadInt32() & 0xFFFF; } } var templateIndex = sitePasswordSeed[0]; var template = SiteTypeHelper.GetTemplateAtRollingIndex(siteType, templateIndex); var password = new StringBuilder(template.TemplateString.Length); for (var i = 0; i < template.TemplateString.Length; ++i) { var characterIndex = sitePasswordSeed[i + 1]; var characterClass = template.TemplateChars[i]; var passwordCharacter = TemplateCharacterClassHelper.GetCharacterAtRollingIndex(characterClass, characterIndex); password.Append(passwordCharacter); } return(password.ToString()); }