public void ANDIntoThis(LogicANFEquation other) { var thisTerms = terms.Keys.ToArray(); this.terms.Clear(); foreach (LogicANDTerm tTerm in thisTerms) { foreach (LogicANDTerm oTerm in other.terms.Keys) { AddTerm(tTerm.Union(oTerm)); } } }
public void SubIntoPlainOr(LogicANFEquation subEq) { int subVarID = subEq.SubVarID; if (!subEq.IsFullyReduced || subVarID == 0) { throw new ArgumentException("subEq is not prepared to be substituted in.", "subEq"); } if (!subEq.IsFullyReduced) { throw new ArgumentException("The equation you are trying to substitute into plainOrEq must be fully reduced.", "subEq"); } bool subVarState = subEq.GetReducedState(); LogicANDTerm subAnd; subVarID *= -1; if (subVarState) // we have to reverse the state because we will be inversing the state of subVarID; { subAnd = LogicANDTerm.ConstantZero; } else { subAnd = LogicANDTerm.ConstantOne; } var array = plainOrEq.ToArray(); plainOrEq.Clear(); for (int i = 0; i < array.Length; i++) { var add = array[i].Key.SubstituteIn(subAnd, subVarID); if (add.IsConstantOne) { throw new Exception("Danger Danger! Logic error by programmer!"); } if (!plainOrEq.Remove(add)) { plainOrEq.Add(add, null); } } }
public string Solve() { LogicANFEquation[] subEqs = new LogicANFEquation[DataSize * 2]; if (!encryptedData.GetBitState(0)) { throw new Exception("I'm screwed."); } else { var isolated = encEqs[0].GetSingleTermVarIDs(); int first = isolated.First(); int last = isolated.Last(); LogicANFEquation newEq1 = new LogicANFEquation(); LogicANFEquation newEq2 = new LogicANFEquation(); newEq1.AddTerm(new LogicANDTerm(new int[] { first })); newEq2.AddTerm(new LogicANDTerm(new int[] { last })); newEq1 = subEqs[first.VarIDToIndex()] = newEq1.CreateSubEq(first, true); newEq2 = subEqs[last.VarIDToIndex()] = newEq2.CreateSubEq(last, true); for (int i = 0; i < DataSize * 2 - 1; i++) { encEqs[i].SubInEq(newEq1); encEqs[i].SubInEq(newEq2); } for (int i = 1; i < DataSize; i++) { LogicANFEquation newSub = encEqs[i].CreateSubEq(encryptedData.GetBitState(i)); for (int j = 0; j < DataSize; j++) { if (j > i) { encEqs[j].SubInEq(newSub); } if (subEqs[j] != null) { subEqs[j].SubInEq(newSub); } } for (int j = DataSize; j < DataSize * 2; j++) { if (subEqs[j] != null) { subEqs[j].SubInEq(newSub); } } subEqs[newSub.SubVarID.VarIDToIndex()] = newSub; } } for (int i = 0; i < DataSize * 2; i++) { if (subEqs[i] != null && subEqs[i].IsFullyReduced) { SubIntoPlainOr(subEqs[i]); for (int j = 0; j < DataSize * 2 - 1; j++) { if (!encEqs[j].IsFullyReduced) encEqs[j].SubInEq(subEqs[i]); } } } //encEqs[62].SubInEq(subEqs[63]); //encEqs[62].CreateSubEq(false); { //int i = DataSize; //while (subEqs[i] == null || subEqs[i].IsFullyReduced) //{ // i++; //} //while (i < DataSize * 2 && subEqs[i] != null && !subEqs[i].IsFullyReduced) //{ // for (int j = 0; j < DataSize * 2 - 1; j++) // { // encEqs[j].SubInEq(subEqs[i]); // //LogicANFEquation test = null; // //try // //{ // // test = encEqs[j].CreateSubEq(encryptedData.GetBitState(j)); // //} // //catch { } // //if (j == 60) // //{ // // //throw new Exception("tell me"); // //} // } // i++; //} } StringBuilder sb = new StringBuilder(); sb.AppendLine("SubInEq's by index:"); for (int i = 0; i < DataSize * 2; i++) { sb.Append(i); sb.Append(": "); if (subEqs[i] == null) { sb.Append("No Equation"); } else { subEqs[i].ToStringBuilder(sb); } sb.AppendLine(); } sb.AppendLine(); sb.AppendLine(); sb.AppendLine("EncEq's by index:"); for (int i = 0; i < DataSize * 2; i++) { sb.Append(i); sb.Append(": "); if (encEqs[i] == null) { sb.Append("No Equation"); } else { encEqs[i].ToStringBuilder(sb); } sb.AppendLine(); } sb.AppendLine(); sb.AppendLine(); sb.AppendLine("plainOrEq:"); foreach (var pair in plainOrEq) { pair.Key.ToStringBuilder(sb); sb.AppendLine(" | "); } return sb.ToString(); }
public void Initialize() { // this next set of 4 repeat loops (nested included) is just a faster way of creating a map of the // operations done to each bit to end up with the encripted bit located at the same index as the index // of xorEq[index]. Faster compared to mapping and getting rid of duplicate procedures of the algorithm // that was provided to us by Nintendo/Alpha Centari. // The variable IDs are equal to the unencrypted bit index + 1. This makes it easy to indicate inverse states by // just making the ID negative. for (int ebitIndex = 0; ebitIndex < DataSize; ebitIndex++) { var tmpEq = new LogicANFEquation(); encEqs[ebitIndex] = tmpEq; for (int termIndex = 0; termIndex <= ebitIndex; termIndex++) { int[] tmp = new int[2] { termIndex + 1, DataSize + ebitIndex - termIndex + 1 }; tmpEq.AddTerm(new LogicANDTerm(tmp)); } } for (int ebitIndex = DataSize * 2 - 2; ebitIndex >= DataSize; ebitIndex--) { var tmpEq = new LogicANFEquation(); encEqs[ebitIndex] = tmpEq; for (int termIndex = 0; termIndex <= DataSize * 2 - ebitIndex - 2; termIndex++) { int[] tmp = new int[2] { ebitIndex - DataSize + 2 + termIndex, DataSize * 2 - termIndex }; tmpEq.AddTerm(new LogicANDTerm(tmp)); } } // Build additional masks based on repeated false values from the first bit or the last bit // These masks will be used as additional equations to further cut down the number of options we have to test. { int lastFalseIdx = DataSize * 2 - 2; while (lastFalseIdx >= DataSize && !encryptedData.GetBitState(lastFalseIdx)) { lastFalseIdx--; } lastFalseIdx++; int numOfTerms = DataSize * 2 - lastFalseIdx; int numOfVarPerTerm = numOfTerms - 1; int firstStart = DataSize * (-1); int secondStart = DataSize * (-2); int[] tmpVars = new int[numOfVarPerTerm]; plainOrEq = new SortedDictionary<LogicANDTerm, object>(); if (lastFalseIdx < DataSize * 2 - 2) { for (int splitPoint = 0; splitPoint < numOfTerms; splitPoint++) { int varIdx = 0; for (; varIdx < splitPoint; varIdx++) { tmpVars[varIdx] = secondStart + varIdx; } for (; varIdx < numOfVarPerTerm; varIdx++) { tmpVars[varIdx] = firstStart - splitPoint + varIdx; } plainOrEq.Add(new LogicANDTerm(tmpVars), null); } } } }
private void SubInEq(LogicANFEquation other, bool inverse, object diffSig) { int otherSubVarID; if (inverse) { otherSubVarID = other.SubVarID * -1; } else { otherSubVarID = other.SubVarID; } var subTerms = other.terms.Keys.ToArray(); var thisTerms = terms.Keys.ToArray(); terms.Clear(); if (subTerms.Length == 0) { subTerms = new LogicANDTerm[] { LogicANDTerm.ConstantZero }; } for (int i = 0; i < thisTerms.Length; i++) { if (thisTerms[i].ContainsVarID(otherSubVarID)) { for (int j = 0; j < subTerms.Length; j++) { AddTerm(thisTerms[i].SubstituteIn(subTerms[j], otherSubVarID)); } if (inverse) { AddTerm(thisTerms[i].DeepCopy(otherSubVarID)); } } else { AddTerm(thisTerms[i]); } } }
private LogicANFEquation CreateSubEq(List<LogicANDTerm> possibles, bool encryptedBitState) { bool works = false; int newSubVarID = 0; int workIdx; for (workIdx = possibles.Count - 1; workIdx >= 0; workIdx--) { newSubVarID = possibles[workIdx].GetSingleVarID(); works = true; foreach (var pair in terms) { if (pair.Key != possibles[workIdx] && pair.Key.ContainsVarID(newSubVarID)) { works = false; break; } } if (works) { break; } } if (!works) { throw new Exception("Cannot make a subsitution equation from this equation."); } LogicANFEquation r = new LogicANFEquation(); r.SubVarID = newSubVarID; foreach (var pair in terms) { if (pair.Key != possibles[workIdx]) { r.terms.Add(pair.Key, null); } } if (encryptedBitState) { r.AddTerm(LogicANDTerm.ConstantOne); } return r; }
public void SubInEq(LogicANFEquation other, bool includeInverse = false) { #if DEBUG if (other.SubVarID == 0) throw new Exception("You are trying to sub in an LogicEquation that is not preped for subbing."); #endif SubInEq(other, false, (object)null); if (includeInverse) { SubInEq(other, true, (object)null); } }