Jump to content

Building a Plugin Security Scheme


Majiir

Recommended Posts

What's the big deal about security, anyway?

Protecting users from malicious plugins has been part of plugin posting policy since the introduction of the plugin loader in KSP 0.14, and in KSP 0.15 this was extended with the introduction of the System.IO and System.Xml namespace bans. While parts are fairly innocuous, plugins have the potential to do extraordinary damage to user systems since they are code executed as part of the game.

At the time, these seemed like common-sense security measures, and plugins today have no less potential to be threats. However, the existing security framework has serious flaws which render it completely useless against an actual attacker.

  • Source code required: Nobody verifies that plugin assemblies were actually built from the same source that's publicly listed.
  • Namespace bans: There are a variety of mechanisms for bypassing these bans which allow full access and may even appear innocuous.
  • Decompiling: Typically, plugins are only decompiled if the source is not available for some reason. For the purposes of security, this is exactly the wrong time. (Note: This refers to decompiling plugins, not the game.)
  • Auditing: There's nobody auditing plugins for security issues at runtime. If strange behavior is encountered it is usually reported, but malware by its nature attempts to mask itself from the user. The most damaging malware will go completely unnoticed to someone not looking for it.

To my knowledge, there have been no malware issues with plugins since the introduction of the plugin loader. Still, security should be preemptive, and the current system requires substantial revision in order to be effective. (In other words, we haven't had a problem; let's not wait until we do to start thinking about improving.)

Multiple paths to the goal

There are several ways to augment plugin security, and one or more can be implemented for some benefit. I will focus on a subset of these techniques in a moment, but first I'll give an overview. This is by no means exhaustive.

  • Security as a convention. This is among the weakest forms of security, but it's the most effective currently in use for KSP. The modding community is fairly close-knit, and it's a crowd that values user security and satisfaction. This is basically "security through nobody trying to be bad."
  • Sandboxing/API restrictions. Namespace bans and other kinds of static analysis fall under this category. It also includes more extensive measures like using interpreted languages, e.g. Lua. (There are many reasons this is a terrible idea, but it's a good example.) In some cases, these measures can provide good security, but they come at a high development cost, loss of modding capabilities or both. It's very difficult to create a sandboxed environment that doesn't make third-party development significantly more limited, and even a perfectly isolated environment can't protect against every attack.
  • Auditing. In the context of KSP plugins, it's easy to inspect source code and determine whether a plugin might be acting as malware. This was the intent behind requiring plugin developers to post source code, but since assemblies themselves are rarely (if ever) inspected, this provides no actual security. Security audits could be feasible if there is some mechanism to verify that a provided assembly matches the given source code.
  • Cryptography. Digital signing can be used to authenticate that an assembly comes from a trusted source. These signatures can be verified by the game at load time, and unsigned or incorrectly signed assemblies can be rejected or restricted. Cryptography offers powerful security guarantees that are contingent on proper implementation (which is often very challenging). Assembly signing is a widely used (your video drivers are probably signed) so in this particular case, implementation is not a roadblock. The greater challenge is determining what counts as a trusted source and how that source can efficiently verify and sign assemblies.

Automated Build + Community Auditing + Assembly Signing

This proposal uses a positive security approach. Sandboxing has benefits, chief among them that it applies equally to all plugins, even ones that don't exist yet. However, under a sandbox model a user doesn't necessarily have any way to know whether a particular plugin is secure.

The process I propose works as follows:

  1. Plugin developer submits source code to an auditing group. This source should be organized in some standard way so there's no ambiguity about how it's to be compiled; an automated build system is ideal.
  2. Auditing group inspects the source code and makes a determination about whether the source is safe. This is clearly not a perfect process, but a well-selected group can provide excellent security guarantees.
  3. If the plugin is approved, the auditing group signs the assembly and returns it to the plugin author.
  4. Users can configure their game to authenticate plugins and reject or restrict any that are not signed. Alternatively, a third-party tool (distributed by the auditing team) can perform verification.

There are important details to work out for each of these stages. For example, there needs to be some way to sign the assembly when a quorum of auditors has approved it, and no single auditor should be able to sign assemblies. A trusted individual could hold the keys, or there could be some cryptographic solution.

I suggest this scheme be completely optional at first. Later iterations can enable signature verification by default or disable sandboxing restrictions for signed assemblies. In particular, the user should always have the choice to override the defaults.

Please post your feedback! I want to emphasize that this is a proposal open to modification. It's also not specifically targeted at anyone; Squad could implement it as part of KSP, but the community could also do it independently.

Link to comment
Share on other sites

Has plugin security become an issue? Or is this just preemptive measures to keep it from becoming a problem at all?

It's preemptive. Historically, efforts to protect against malware have actually been more problematic than malware itself.

Link to comment
Share on other sites

Ideally, we would have a source code submission in a zip file to an automated tester somewhere. The tester bot would compile the source, run it to make sure it wasn't doing anything obviously naughty, then submit the source for human review. The only way a DLL should be created is after passing a set of reviews. Also, the DLL should have a hash value to verify that the coder is handing out the verified compiled code.

Otherwise, the easier/faster way is a warning on spaceport about the safety of the plugin being undetermined, and using it is at your own risk. Basically like visiting sketchy websites and downloading "videoplayer.exe", you know the risks.

Edited by ummwut
Link to comment
Share on other sites

Automated testing is in the same category as sandboxing. There are all kinds of bad things it'll never pick up. You can make static analysis a part of the process, but that's a lot of work for very little payoff.

Link to comment
Share on other sites

Please read my post again. The word 'obvious' being key here; I don't want a comprehensive automatic analysis. Simply checking to see if the plugin starts digging around outside the install folder or attempts an outbound network connection can be enough to raise a red flag. Additionally, monitoring such events is simple to do.

Link to comment
Share on other sites

I don't understand the use case. If something is obvious, wouldn't manual analysis find it? The potential for false alarms is high, and I don't see why there would be such a high volume of malware submissions to make it useful. Plus, automated analysis as a first stage could have a negative impact on the quality of the manual audits. You could check for a plugin using certain parts of the framework API, but this wouldn't save any time and can't automatically disqualify a submission either. (Even something suspicious like spawning another process might have legitimate uses.)

Link to comment
Share on other sites

  • 5 months later...

This thread has come up in conversation a few times today.

Squad is likely not interested, so I think the modding community should proceed with a proof of concept. This would enable users to digitally verify the security and origins of plugins. It may be possible to optionally restrict unsigned assemblies for users with a preference for security. I think that both auditing and signature verification are easily accomplished, but an automated build strategy may be more challenging. That said, auditors will necessarily need to be versed in plugin development, so building plugins manually for signing is not a significant barrier.

Link to comment
Share on other sites

I'm honestly surprised that the a) the modding community has been operating pretty much on the honor system for so long and B) that a big malware issue hasn't happened yet. It's a good reflection on the character and quality of the individuals making all these awesome plugins. :)

That being said, I'm surprised that the lack of plugin security has gone on so long. All the other games I've played that have allowed mods, the mods are pretty much texture replacement/config edits/scripting specific to the game's engine. Basically just stuff that tweaks the stuff the game is already doing. KSP has plugins that actually have their own code that executes. Big difference. I am ENTIRELY in favor of having something like an audit group digitally signing plugins. I am willing to wait a few days to a week for an update for a mod if I can get a guarantee that the code in the .dll isn't going to seriously mess my computer up or endanger my personal information. As an aside, I hope that Squad continues to develop their mod support such that plugin devs can get their hands on a pre-release of some kind so they can have their plugin updated, tested, signed, and available for download right after a new version of KSP comes out. I heard that a lot of mod devs got that this time around in .23 and I personally loved having soooo many big mods updated to 0.23 within a few hours of 0.23 coming out.

Back to the issue described in the OP, this is one of the reasons I'm less likely to try out a plugin by newcomers to the scene. Now if it's something by Majiir or NathanKell or Sabian or Ferram or any of the other big names in the modding dev community, they've proven themselves as responsible and trustworthy devs in my eyes. However, if a new plugin comes out and it looks interesting and I can see that it's signed, I'm going to be a lot less sketched out when downloading and firing it up. This leads to me trying out new mods that I might have never tried out before. What Majiir is proposing would give me a less of an "man, idk, this guy only has like 12 forum posts, I think I'll pass" feeling. That person could have been playing KSP for months and months and decided to write a plugin and just registered on the forum to release it. I'm not saying everyone is judged by forum post count, but a lot of people do judge that way. It's one of a very few metrics available.

I can only see something like what Majiir outlined in his OP as good for KSP, the users, and mod devs. As soon as someone writes a plugin that does something bad, it's probably going to spread like Internet wildfire among gaming communities. People will write web comics about the incident. There'd be a lot of negative attention. Malware devs might see the one incident and think that maybe they want to try their hand at it too. There's all kinds of stuff that could happen at that point. It's just a bad scenario and one that I feel is not an if, but when. :-/

What I don't want to see happen is the audit group nitpicking someone's code. I'm sure there are more efficient ways to do stuff, but as long as it doesn't do something bad, let it pass. It's a different case if the code is purposely written to obscure its true purpose, so I don't think some general guidelines are unreasonable. Code has to be at least understandable to be audited.

I can't contribute to such a system as what Majiir is pointing out, but I sure as heck would use it. I'll support signed mods over unsigned ones.

Link to comment
Share on other sites

I honestly think you're trying to solve the problem that doesn't exist in the first place.

Whole history of malware on PC has proved that it's mostly a social problem, not a technical one, and as such, trying to solve it using technical measures is doomed to fail. All AV products I've seen so far do much more harm that good. The only effective defense is user education - if user keeps launching all "please-run-me-you-stupid-moron.exe"'s there is little technology can do to stop him.

Audit-review-approve process will only introduce more bureaucracy and delays into releasing stuff, and this will especially be problematic for newly released mods since they tend to have a lot of bugs and as such require a series of quick releases to fix upcoming problems. Since I have very little time that I can dedicate to mod development, I'd rather spend it in actual development, not pushing auditors to publish build ASAP as my users wait for the fix. So I'd be first to direct my users to disable this check, and if they would rather not - well, it won't be not my problem anymore.

And again the question is who are going to be these auditors? Really good professional devs usually don't have a lot of spare time, while mediocre devs would miss problems, especially if they are well-masked as legit code (I can think of several ways to do that - for example how many devs here know what expression trees are for in .NET?). I've been doing security audits for commercial products so I know this area fairly good. An auditor needs to know what to look for in order to actually find a problem, because most would not understand a problem even if pointed at it.

Someone brought up video drivers as example for signed software. I only hope that person actually know what it takes to get WHQL signature (hint - MS does TONS of testing before signing the driver). Is this audit groups going to do similar amount of testing? And if so - who's picking up the tab (I can tell you it's quite expensive process)?

Edited by asmi
Link to comment
Share on other sites

Audit-review-approve process will only introduce more bureaucracy and delays into releasing stuff, and this will especially be problematic for newly released mods since they tend to have a lot of bugs and as such require a series of quick releases to fix upcoming problems. Since I have very little time that I can dedicate to mod development, I'd rather spend it in actual development, not pushing auditors to publish build ASAP as my users wait for the fix. So I'd be first to direct my users to disable this check, and if they would rather not - well, it won't be not my problem anymore.

And again the question is who are going to be these auditors? Really good professional devs usually don't have a lot of spare time, while mediocre devs would miss problems, especially if they are well-masked as legit code (I can think of several ways to do that - for example how many devs here know what expression trees are for in .NET?). I've been doing security audits for commercial products so I know this area fairly good. An auditor needs to know what to look for in order to actually find a problem, because most would not understand a problem even if pointed at it.

I just want to punctuate this point (clarity line breaks are mine). Auditors would necessarily be auditing in their spare time, which introduces additional delays in mod release time (unless you can rely on them to drop everything at a moment's notice to weed through someone's code...) This is the sort of thing that needs a full-time position and, while I am not at all opposed to code review (<deity> knows we all could use one!), I don't want to have to sit around waiting for someone to have free time to sign my app in order to release it.

Link to comment
Share on other sites

The largest potential flaw I can see with this is the audit process. Namely, who would do the audits and how long it would take. Consider 0.24 release day. The new version drops with some change to game architecture that breaks a majority of mods. I sit down, spend the next few hours fixing up my mod, and post the new source code to the auditing forum. Unfortunately, no one is available to do the required (say 3, or at most 5) audits. Why? Because the other mod authors are all working on their own updates, or auditing the mods that came in half an hour before mine.

For normal, day-to-day updates of mods, I imagine turnaround would be pretty good. Patch day would be quite a different story. Now, this doesn't necessarily invalidate the whole idea, but it is worth considering. After all, I imagine most of the people willing (and able) to do auditing work are already involved with mod development. This assumes you can get enough volunteers to begin with (probably not unreasonable, but its hard to say).

Link to comment
Share on other sites

I just want to punctuate this point (clarity line breaks are mine). Auditors would necessarily be auditing in their spare time, which introduces additional delays in mod release time (unless you can rely on them to drop everything at a moment's notice to weed through someone's code...) This is the sort of thing that needs a full-time position and, while I am not at all opposed to code review (<deity> knows we all could use one!), I don't want to have to sit around waiting for someone to have free time to sign my app in order to release it.

Exactly my position. I'm not against audit in principle (infact I'd love someone to do it for my code) - I'm against delays that will be unavoidable as long as modders won't get some sort of "service guarantee", i.e. someone will ensure response within certain amount of time.

Link to comment
Share on other sites

Consider 0.24 release day. The new version drops with some change to game architecture that breaks a majority of mods.

Why would there be a need to audit a mod completely over and over? It suffices to only audit the changes that have actually been made. In the case of releasing a hotfix to restore KSP update compatibility, the changes are usually quite small.

Link to comment
Share on other sites

Why would there be a need to audit a mod completely over and over? It suffices to only audit the changes that have actually been made. In the case of releasing a hotfix to restore KSP update compatibility, the changes are usually quite small.

I'd imagine taking a quick look at git commits would be sufficient for that, wouldn't it?

Link to comment
Share on other sites

The largest potential flaw I can see with this is the audit process. Namely, who would do the audits and how long it would take. Consider 0.24 release day. The new version drops with some change to game architecture that breaks a majority of mods. I sit down, spend the next few hours fixing up my mod, and post the new source code to the auditing forum. Unfortunately, no one is available to do the required (say 3, or at most 5) audits. Why? Because the other mod authors are all working on their own updates, or auditing the mods that came in half an hour before mine.

For normal, day-to-day updates of mods, I imagine turnaround would be pretty good. Patch day would be quite a different story. Now, this doesn't necessarily invalidate the whole idea, but it is worth considering. After all, I imagine most of the people willing (and able) to do auditing work are already involved with mod development. This assumes you can get enough volunteers to begin with (probably not unreasonable, but its hard to say).

Squad having a program to apply for a pre-release versions of KSP would help. Being able to fix up your mod and get it signed for a new version of KSP before it becomes available to the masses combined with what Blizzy78 said about only needing to audit new code could potentially alleviate a ton of work. That way a signed release of your mod is available the day of release for a new version of KSP without having to do all the work the day of the release.

Link to comment
Share on other sites

Currently anyoner can sign up for spaceport, that includes people outside of our awesome mod community. This person could easily post a plugin called "Physics lag reducer" and fill it with self replicating malware, viruses and post it for download. It would be caught eventually but by then it would be too late.

It is far to easy for users OUTSIDE our wonderful community to post malicious content. Plugins should have some verification process for at minimum new people to the forums and spaceport. As well as having a way for trusted authors not to jump through hoops to update their mods.

Link to comment
Share on other sites

I honestly think you're trying to solve the problem that doesn't exist in the first place.

See my original post:

To my knowledge, there have been no malware issues with plugins since the introduction of the plugin loader. Still, security should be preemptive, and the current system requires substantial revision in order to be effective. (In other words, we haven't had a problem; let's not wait until we do to start thinking about improving.)

I don't want to wait around for the scenario Eadrom describes to start cobbling together a security scheme. Your line of thinking could also be used to argue that countries shouldn't have missile defense.

I just want to punctuate this point (clarity line breaks are mine). Auditors would necessarily be auditing in their spare time, which introduces additional delays in mod release time (unless you can rely on them to drop everything at a moment's notice to weed through someone's code...) This is the sort of thing that needs a full-time position and, while I am not at all opposed to code review (<deity> knows we all could use one!), I don't want to have to sit around waiting for someone to have free time to sign my app in order to release it.

You don't have to be signed in order to release. It's quite reasonable to release an update as soon as it's ready and then post a link to a signed assembly a couple days later. Only users with a preference for security over speediness will be affected, and most importantly, those users are making that choice to wait. I'm certainly not proposing that signed assemblies be mandatory. Should we ever reach the point where a large portion of published mods are signed, it might be worth changing verification from opt-in to opt-out, but it should always be the user's choice. (For example, mod developers will want to disable verification on their development copy.)

Squad having a program to apply for a pre-release versions of KSP would help. Being able to fix up your mod and get it signed for a new version of KSP before it becomes available to the masses combined with what Blizzy78 said about only needing to audit new code could potentially alleviate a ton of work. That way a signed release of your mod is available the day of release for a new version of KSP without having to do all the work the day of the release.

There's a small group of modders with pre-release access (although it's not by application). The criteria for that group makes its members well-suited to auditing from a trustworthiness perspective, though it doesn't say much about their skill as security auditors. Again, even if you release on patch day, you can always be signed later. There are even mechanisms where an assembly can be signed and verified without users redownloading.

Link to comment
Share on other sites

That certainly helps alleviate most of my concerns. I would participate in signing my stuff. Have you done any architecture work yet? I assume there would need to be a trusted signature checker mod to validate other installed mods, as an internal checker couldn't be trusted.

Link to comment
Share on other sites

Here is a pretty rough version of a simple method for verifying all DLLs in the GameData directory match a hash that is downloaded from a "trusted" website. If all the files check, the user doesn't see anything. If a DLL's hash doesn't match, or there is no hash stored on the web, they are notified with a dialog box. Currently, unlike the version compatibility checker, there is no public method to allow mods to look in and see if they are signed, but it could be included. This code is not ready for public distribution, and all rights are still reserved to me. You may however download and run it yourself if you like. It will flag itself as unsigned, because I've updated it since I posted the hash. The mods that I have hashes up for are:

Engineer Redux

Toolbar

FAR

Kerbal Alarm Clock

SteamGauges

Thoughts? Major holes in security? Oh, and I would be surprised if it ran on anything but Windows.


[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]using [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] System;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]using [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] System.Security.Cryptography;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]using [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] System.IO;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]using [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] UnityEngine;[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]

[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]namespace [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] SignatureChecker[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
{
[[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]KSPAddon[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]KSPAddon[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]Startup[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].MainMenu, [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]true[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2])][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] internal [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]class [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]SigChecker[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] : [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]MonoBehaviour[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] private[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]string[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] webdir = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][COLOR=#222222][URL]https://sites.google.com/site/ksphash/[/URL][/COLOR][/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT] [FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]

[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] //This is the main method that runs at game startup[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] public[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]void[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] Start()[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] Debug[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].Log([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"Starting Signature Checker..."[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] path = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]Directory[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].GetCurrentDirectory(); [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]//KSP directory[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] path = path + [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"\\GameData"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] results;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] try[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] dlls = getAllDLLs(path);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] results = checkHashes(dlls);
}
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] catch[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
results = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"Signature Checker encountered an error, and did not complete."[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }

[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] if[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] (!results.Equals([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]""[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]))[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] PopupDialog[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].SpawnPopupDialog([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"Hash Check Results"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2], results, [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"Continue"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2], [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]false[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2], [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]HighLogic[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].Skin);[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] Debug[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].Log([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"Signature Checker has completed."[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]);
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }



[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] private[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] checkHashes([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] files)[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] results = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]""[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] byte[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] fileHash;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] string[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] fileHashString;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] HashAlgorithm[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] hash = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]HashAlgorithm[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].Create();[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] foreach[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] ([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] dll [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]in[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] files)[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
{
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] using[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] ([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]FileStream[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] file = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]new[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]FileStream[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2](dll, [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]FileMode[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].Open))[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
fileHash = hash.ComputeHash(file);
fileHashString = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]BitConverter[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].ToString(fileHash);[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] fname = dll.Substring(dll.LastIndexOf([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"\\"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2])+1);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] fname = fname.Substring(0, fname.Length-(fname.Length-fname.LastIndexOf([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]'.'[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]))); [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]//Horrible way of stripping off the .dll at the end[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] WWW[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] trustedsource = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]new[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]WWW[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2](webdir+fname.ToLower());
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]float[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] start = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]Time[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].time;[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] while[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] ([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]Time[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].time - start < 2) [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]//Wait 2 seconds for loading...there is a better way to do this[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] if[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] (trustedsource.isDone)[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] if[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] (trustedsource.error == [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]null[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] || !trustedsource.error.Contains([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"404"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]))[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] String[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] foundHash = trustedsource.text;[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] foundHash = foundHash.Substring(foundHash.LastIndexOf([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]"Hash:"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]) + 5, 59);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] if[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] (!fileHashString.Equals(foundHash))[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
results = results + fname + [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]" hash is invalid!\n"[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] Debug[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].LogWarning(fname + [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"'s hash is invalid!"[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]);
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]Debug[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].LogWarning([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"Computed: "[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] + fileHashString);[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] Debug[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].LogWarning([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"Check: "[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] + foundHash);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] else[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] Debug[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].Log(fname + [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"'s hash cheked."[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }
}
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] else[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] Debug[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].LogWarning([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"Could not locate "[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] + fname+[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"'s hash file to check against."[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]);[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] results = results + [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"Could not find "[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] + fname + [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]"'s hash to verify!\n"[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] break[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2];[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }
}
}
}
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]return[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] results;[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }

[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//This method returns a list containing paths to all DLLs found[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//recursivly in this directory and its sub directories[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]private[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] getAllDLLs([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] path)[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]{
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000] //First look through all files in this directory, and add the DLLs[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] files= [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][0];[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] foreach[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] ([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] f [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]in[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]Directory[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].GetFiles(path))[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
{
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] if[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] (f.Contains([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515][FONT=Consolas][SIZE=2][COLOR=#a31515]".dll"[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]))[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] oldfiles = files;[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
files = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][oldfiles.Length + 1];[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] oldfiles.CopyTo(files, 0);
files[oldfiles.Length] = f;
}
}
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//Now iterate through all subdirectories and do the same[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] subDirs = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]Directory[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2].GetDirectories(path);[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] foreach[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] ([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] sd [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]in[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] subDirs)
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] {
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af] String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] res = getAllDLLs(sd);
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]String[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][] oldfiles = files;
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] files = [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]string[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][res.Length + oldfiles.Length];[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
oldfiles.CopyTo(files, 0);
res.CopyTo(files, oldfiles.Length);
}
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff] return[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] files;[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] }
}
}
[/SIZE][/FONT][/SIZE][/FONT]

Edited by Trueborn
Link to comment
Share on other sites

The problem as I see it is that this will only tell you if a bad plugin has already been loaded; that's not security. For a security scheme to be of any use it needs to prevent any plugins that have invalid identification from running or loading at all. How to compromise this with plugins that are not signed at all and remain secure is beyond me, but if you have a list of hashes and a plugin doesn't match it's hash, that plugin is a clear and present danger; being alerted that you just ran dangerous code is of limited use.

Link to comment
Share on other sites

Here is a pretty rough version of a simple method for verifying all DLLs in the GameData directory match a hash that is downloaded from a "trusted" website. If all the files check, the user doesn't see anything. If a DLL's hash doesn't match, or there is no hash stored on the web, they are notified with a dialog box. Currently, unlike the version compatibility checker, there is no public method to allow mods to look in and see if they are signed, but it could be included.

...

Thoughts? Major holes in security?

I think it's too early to start coding. There are still big questions to answer about how a security system should function at a high level.

That said, I want to point out that signing and hashing are related but not the same thing. With hashing, the user must always download a list of approved hashes. Digitally signing an assembly means that the plugin comes packaged with cryptographic proof that the assembly was signed, and that proof can be verified by the client without contacting any servers. In other words, a plugin can be verified without the client having any prior knowledge of that plugin. The only prior knowledge that's needed is a set of auditor certificates to be trusted, and those will change infrequently.

The problem as I see it is that this will only tell you if a bad plugin has already been loaded; that's not security. For a security scheme to be of any use it needs to prevent any plugins that have invalid identification from running or loading at all. How to compromise this with plugins that are not signed at all and remain secure is beyond me, but if you have a list of hashes and a plugin doesn't match it's hash, that plugin is a clear and present danger; being alerted that you just ran dangerous code is of limited use.

There are a few modes of operation that a user might be interested in.

  • User chooses to run both signed and unsigned mods. Any valid signed mods are listed on startup so that if the user expects a mod to be signed and it isn't, he can complain.
  • User chooses to run both signed and unsigned mods. Some mods are configured to require a valid signature, and others are not. If a mod that's supposed to be signed cannot be verified, it's disabled and a warning appears.
  • User chooses to run only signed and verified mods. Any other mod is disabled.

Along those lines, there are also several ways a user might want a mod to be signed. Some may want an assembly to be signed by at least two auditors, while others might want each mod to be signed by its respective author. In this discussion, we need to establish both which modes we aim to support and which modes we make default.

For disabling mods before they execute, we have at least two options. Users could start a launcher instead of the KSP assembly, and that launcher could verify plugins before allowing KSP to start. This is easy to do, but it presents usability issues. A second option is to use IL injection, which would be more transparent to the user but would also be harder to maintain and potentially controversial.

Link to comment
Share on other sites

while others might want each mod to be signed by its respective author.

I'd rather have this as a requirement. Self-signed DLLs wouldn't contribute to a "secure" feeling in the sense of auditing, but at least the user can be sure that the DLL comes from the respective author rather than a third party. Of course each user could disable any checks for self-signed certificates.

Also, certificates used to self-sign DLLs should be signed by the auditing team/mod/quorum/...

Link to comment
Share on other sites

Alright, all valid.

Quick overview of digital signatures / public key encryption for non-programmers who might be reading:

  • Digital signatures work by using two encryption keys, a public and a private key. They are mathematically related, but can't be determined directly from one another.
  • The data to be signed is hashed (you get a unique, short code for that data), and the hash is then encrypted by the signers private key.
  • The user downloads both the data, and the encrypted hash. Then, using the signers public key they decrypt the hash. They perform their own hash on the data, and if it matches the unencrypted version, the signature is valid.
  • http://en.wikipedia.org/wiki/Digital_signature for more detail

So, the user must keep a set of certificates which are used to verify the digital signatures. They will only have to contact the server when:

  • A certificate has expired - the length of time a certificate is valid is arbitrary, but lets say 6 months on the short end for our uses
  • A mod is downloaded that has been signed by someone who the user doesn't have a certificate for, either developer or auditor

This doesn't include the possibility of revoking certificates, which, if we're going to go this far, we really might as well do. This requires checking with the sever at every run.

A certificate needs to contain:

  • A unique user ID - whose certificate is this?
  • The user's public key
  • The expiration date of the certificate - helps to secure against compromised keys, even if we don't know they're compromised

Multiple signatures are reasonably straight forward, you just encrypt the data multiple times, and then decrypt it again (in the right order!).

Link to comment
Share on other sites

This doesn't include the possibility of revoking certificates, which, if we're going to go this far, we really might as well do. This requires checking with the sever at every run.

Not necessarily, you can also cache the result for X days, at the expense of security, of course. But since revocations shouldn't occur all too often, this might be an acceptable compromise.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...