public bool IsValid(string rootFolder) { if (Exists(rootFolder)) { int size = (int)new FileInfo(Path.Combine(rootFolder, fileName)).Length; if (size == fileSize) { byte[] buffer = File.ReadAllBytes(Path.Combine(rootFolder, fileName)); byte[] hash = XCalcSig.CalculateDigest(buffer, (int)fileHashOffset, (int)fileHashLength); buffer = null; bool result = hash.CompareTo(fileHash); hash = null; return(result); } } return(false); }
public bool Sign(byte[] XboxHDKey, bool skipContentHashing, out string errorMessage) { if (Equals(null, XboxHDKey) || XboxHDKey.Length != 0x10) { errorMessage = "Bad key"; return(false); } byte[] buffer, hash; //calculate content hashes if (!skipContentHashing) { object result; if (!GetSection(Types.SectionType.TableOfContents, out result)) { errorMessage = "Failed to parse section data"; return(false); } Types.Section section = Sections[1]; Types.TableOfContents fileTable = (Types.TableOfContents)result; //parsed toc data foreach (Types.TableEntry file in fileTable.entries) { if (!file.Exists(Path.GetDirectoryName(FilePath))) { errorMessage = string.Format("Content file not found: {0}", file.fileName); return(false); } uint hashStartOffset = file.fileHashOffset; uint hashLength = file.fileHashLength; uint size = (uint)new FileInfo(Path.Combine(Path.GetDirectoryName(FilePath), file.fileName)).Length; if (size != file.fileSize) { //errorMessage = string.Format("The size of the file \"{0}\" is invalid\n\nExpected size: {1} ({2} bytes)\nActual size: {3} ({4} bytes)", file.fileName, file.fileSize.RoundBytes(), file.fileSize, size.RoundBytes(), size); //return false; //instead of returning an error here I decided to correct the file size, in case of modders :) buffer = BitConverter.GetBytes(size); IO.Position = (((section.sectionOffset + fileTable.entryTableOffset) + file.entryOffset) + 0x8); IO.Write(buffer, 0, 4); //file size //set hash to cover entire file IO.Write(new byte[4], 0, 4); //hash start offset IO.Write(buffer, 0, 4); //hash length hashStartOffset = 0; hashLength = size; } buffer = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(FilePath), file.fileName)); hash = XCalcSig.CalculateDigest(buffer, (int)hashStartOffset, (int)hashLength); IO.Position = ((section.sectionOffset + 0xC) + (file.fileHashIndex * 0x14)); IO.Write(hash, 0, 0x14); } IO.Flush(); } //calculate section hashes foreach (Types.Section section in Sections) { if (!section.IsAllocated) { continue; } buffer = new byte[section.sectionLength]; IO.Position = section.sectionOffset; IO.Read(buffer, 0, (int)section.sectionLength); hash = XCalcSig.CalculateDigest(buffer); IO.Position = section.hashOffset; IO.Write(hash, 0, 0x14); } IO.Flush(); //calculate header "signature" buffer = new byte[(Header.headerSize - 0x14)]; IO.Position = 0x14; IO.Read(buffer, 0, (int)(Header.headerSize - 0x14)); hash = XCalcSig.CalculateNonRoamable(BitConverter.GetBytes(Header.titleId), XboxHDKey, buffer); IO.Position = 0; IO.Write(hash, 0, 0x14); IO.Flush(); buffer = null; hash = null; errorMessage = null; return(true); }
public keyForm() { InitializeComponent(); Shown += (s, e) => { LoadKeys(); }; importButton.Click += (s, e) => { using (OpenFileDialog open = new OpenFileDialog()) { open.Filter = "Xbox 360 Keyvault (*.bin)|*.bin|All Files (*.*)|*.*"; if (open.ShowDialog() != DialogResult.OK) { return; } string consoleSerial, motherboardSerial; if (XCalcSig.FromKV(open.FileName, out consoleSerial, out motherboardSerial)) { consoleSerialBox.Text = consoleSerial; motherboardSerialBox.Text = motherboardSerial; return; } MessageBox.Show("Failed to read KV file"); } }; removeButton.Click += (s, e) => { if (!(Equals(null, keyList.Items) && keyList.Items.Count > 0)) { foreach (ListViewItem item in keyList.CheckedItems) { keys.Remove(item.Text, item.SubItems[1].Text.ToBytes(true)); keyList.Items.Remove(item); } LoadKeys(); } }; makeButton.Click += (s, e) => { if (makeAliasBox.Text.Length == 0) { MessageBox.Show("Alias name must not be empty"); return; } long consoleSerial; if (consoleSerialBox.Text.Length != 12 || !long.TryParse(consoleSerialBox.Text, out consoleSerial)) { MessageBox.Show("Invalid console serial"); return; } if (motherboardSerialBox.Text.Length != 16 || !motherboardSerialBox.Text.IsHex()) { MessageBox.Show("Invalid motherboard serial"); return; } string alias = makeAliasBox.Text; if (keys.Contains(alias)) { MessageBox.Show("Alias already in use"); return; } byte[] key = XCalcSig.MakeXboxHDKey(consoleSerialBox.Text, motherboardSerialBox.Text); if (keys.Contains(key)) { MessageBox.Show("Key already added under another alias"); return; } keys.Add(new UI.Keys.Key() { alias = alias, key = key }); LoadKeys(); }; addKeyButton.Click += (s, e) => { if (addAliasBox.Text.Length == 0) { MessageBox.Show("Alias name must not be empty"); return; } if (keyBox.Text.Length != 32 || !keyBox.Text.IsHex()) { MessageBox.Show("Invalid XboxHDKey"); return; } string alias = addAliasBox.Text; if (keys.Contains(alias)) { MessageBox.Show("Alias already in use"); return; } byte[] key = keyBox.Text.ToBytes(true); if (keys.Contains(key)) { MessageBox.Show("Key already added under another alias"); return; } keys.Add(new UI.Keys.Key() { alias = alias, key = key }); LoadKeys(); }; }