├── README.md ├── SharpHIBP.sln └── SharpHIBP ├── App.config ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── SharpHIBP.csproj └── SharpHIBP.csproj.user /README.md: -------------------------------------------------------------------------------- 1 | # SharpHIBP 2 | A C# Tool to gather information about email breaches 3 | 4 | ## Usage 5 | 6 | Simple: 7 | This will just outputs the name of the breach the email is located in using the --email you can give it a single email to look up 8 | ``` 9 | C:> SharpHIBP.exe --api [API KEY] --email example@google.com 10 | Email: example@google.com 11 | [ 12 | { 13 | "Name":"2844Breaches" 14 | } 15 | ] 16 | ``` 17 | Verbose Usage: 18 | This will output more info about the breach the email is located in, this way you know if the information you are looking for is in it 19 | ``` 20 | SharpHIBP.exe --api [API KEY] --email example@google.com --verbose 21 | Email: example@google.com 22 | [ 23 | { 24 | "Name":"2844Breaches", 25 | "Title":"2, 26 | 844 Separate Data Breaches", 27 | "Domain":"", 28 | "BreachDate":"2018-02-19", 29 | "AddedDate":"2018-02-26T10:06:02Z", 30 | "ModifiedDate":"2018-02-26T10:06:02Z", 31 | "PwnCount":80115532, 32 | "Description":"In February 2018, 33 | a massive collection of almost 3, 34 | 000 alleged data breaches was found online. Whilst some of the data had previously been seen in Have I Been Pwned, 35 | 2, 36 | 844 of the files consisting of more than 80 million unique email addresses had not previously been seen. Each file contained both an email address and plain text password and were consequently loaded as a single "unverified" data breach.", 37 | "LogoPath":"https://haveibeenpwned.com/Content/Images/PwnedLogos/List.png", 38 | "DataClasses":[ 39 | "Email addresses", 40 | "Passwords" 41 | ], 42 | "IsVerified":false, 43 | "IsFabricated":false, 44 | "IsSensitive":false, 45 | "IsRetired":false, 46 | "IsSpamList":false, 47 | "IsMalware":false, 48 | "IsSubscriptionFree":false 49 | } 50 | ] 51 | ``` 52 | 53 | File list Usage: 54 | You can pass it a file containing a list of emails as well the thread has been set by default each 7 seconds so to not get timed out this is based on the PWNED 1 Subscription 55 | > [!TIP] 56 | > This also has a Verbose Method 57 | ``` 58 | C:> SharpHIBP.exe --api [API KEY] --file emails.txt 59 | Email: example@google.com 60 | [ 61 | { 62 | "Name":"2844Breaches" 63 | } 64 | ] 65 | ``` 66 | -------------------------------------------------------------------------------- /SharpHIBP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34031.279 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHIBP", "SharpHIBP\SharpHIBP.csproj", "{E71E608C-956E-4390-BA5A-6C23EE1CF04B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {E71E608C-956E-4390-BA5A-6C23EE1CF04B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {E71E608C-956E-4390-BA5A-6C23EE1CF04B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {E71E608C-956E-4390-BA5A-6C23EE1CF04B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {E71E608C-956E-4390-BA5A-6C23EE1CF04B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {BC4D9842-9581-4DD7-87C3-061B21128FB0} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SharpHIBP/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /SharpHIBP/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | string apiKey = null; 11 | string email = null; 12 | string userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"; 13 | string filename = null; 14 | bool verbose = false; // Verbose flag for more breach data output 15 | 16 | for (int i = 0; i < args.Length; i += 2) 17 | { 18 | if (args[i] == "--api") 19 | { 20 | apiKey = args[i + 1]; 21 | } 22 | else if (args[i] == "--email") 23 | { 24 | email = args[i + 1]; 25 | } 26 | else if (args[i] == "--file") 27 | { 28 | filename = args[i + 1]; 29 | } 30 | else if (args[i] == "--verbose") 31 | { 32 | verbose = true; 33 | } 34 | } 35 | 36 | if (string.IsNullOrEmpty(apiKey)) 37 | { 38 | Console.WriteLine("API key is required. Usage: SharpHIBP.exe --api [YourAPIKey] [--email email] [--file file containing email list] [--verbose Will output more info about the breach]"); 39 | return; 40 | } 41 | 42 | if (!string.IsNullOrEmpty(email)) 43 | { 44 | if (verbose) 45 | { 46 | await CheckEmailVerbose(apiKey, email, userAgent); 47 | } 48 | else 49 | { 50 | await CheckEmail(apiKey, email, userAgent); 51 | } 52 | } 53 | else if (!string.IsNullOrEmpty(filename)) 54 | { 55 | if (File.Exists(filename)) 56 | { 57 | string[] emails = File.ReadAllLines(filename); 58 | foreach (var singleEmail in emails) 59 | { 60 | if (verbose) 61 | { 62 | await CheckEmailVerbose(apiKey, singleEmail, userAgent); 63 | } 64 | else 65 | { 66 | await CheckEmail(apiKey, singleEmail, userAgent); 67 | } 68 | await Task.Delay(7500); 69 | } 70 | } 71 | else 72 | { 73 | Console.WriteLine("File not found."); 74 | } 75 | } 76 | else 77 | { 78 | Console.WriteLine("No email or file specified. Usage: SharpHIBP.exe --api [YourAPIKey] [--email email] [--file file containing email list] [--verbose Will output more info about the breach]"); 79 | } 80 | } 81 | 82 | static async Task CheckEmail(string apiKey, string email, string userAgent) 83 | { 84 | string apiUrl = $"https://haveibeenpwned.com/api/v3/breachedaccount/{Uri.EscapeDataString(email)}/"; 85 | 86 | using (HttpClient httpClient = new HttpClient()) 87 | { 88 | httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent); 89 | httpClient.DefaultRequestHeaders.Add("hibp-api-key", apiKey); 90 | 91 | try 92 | { 93 | HttpResponseMessage response = await httpClient.GetAsync(apiUrl); 94 | 95 | if (response.IsSuccessStatusCode) 96 | { 97 | string content = await response.Content.ReadAsStringAsync(); 98 | Console.WriteLine($"Email: {email}"); 99 | Console.WriteLine(FormatJson(content)); 100 | } 101 | else 102 | { 103 | Console.WriteLine($"Email: {email}"); 104 | Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); 105 | } 106 | } 107 | catch (HttpRequestException ex) 108 | { 109 | Console.WriteLine($"Email: {email}"); 110 | Console.WriteLine($"Request Exception: {ex.Message}"); 111 | } 112 | } 113 | } 114 | 115 | static async Task CheckEmailVerbose(string apiKey, string email, string userAgent) 116 | { 117 | string apiUrl = $"https://haveibeenpwned.com/api/v3/breachedaccount/{Uri.EscapeDataString(email)}/?truncateResponse=false"; 118 | 119 | using (HttpClient httpClient = new HttpClient()) 120 | { 121 | httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent); 122 | httpClient.DefaultRequestHeaders.Add("hibp-api-key", apiKey); 123 | 124 | try 125 | { 126 | HttpResponseMessage response = await httpClient.GetAsync(apiUrl); 127 | 128 | if (response.IsSuccessStatusCode) 129 | { 130 | string content = await response.Content.ReadAsStringAsync(); 131 | Console.WriteLine($"Email: {email}"); 132 | Console.WriteLine(FormatJson(content)); 133 | } 134 | else 135 | { 136 | Console.WriteLine($"Email: {email}"); 137 | Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); 138 | } 139 | } 140 | catch (HttpRequestException ex) 141 | { 142 | Console.WriteLine($"Email: {email}"); 143 | Console.WriteLine($"Request Exception: {ex.Message}"); 144 | } 145 | } 146 | } 147 | 148 | static string FormatJson(string json) 149 | { 150 | int level = 0; 151 | var result = string.Empty; 152 | var indent = " "; // 4 spaces for indentation 153 | 154 | foreach (var character in json) 155 | { 156 | if (character == '{' || character == '[') 157 | { 158 | result += character + Environment.NewLine + new string(' ', level++ * 4); 159 | } 160 | else if (character == '}' || character == ']') 161 | { 162 | result += Environment.NewLine + new string(' ', --level * 4) + character; 163 | } 164 | else if (character == ',') 165 | { 166 | result += character + Environment.NewLine + new string(' ', level * 4); 167 | } 168 | else 169 | { 170 | result += character; 171 | } 172 | } 173 | 174 | return result; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /SharpHIBP/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SharpHIBP")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SharpHIBP")] 13 | [assembly: AssemblyCopyright("Copyright © 2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e71e608c-956e-4390-ba5a-6c23ee1cf04b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SharpHIBP/SharpHIBP.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E71E608C-956E-4390-BA5A-6C23EE1CF04B} 8 | Exe 9 | SharpHIBP 10 | SharpHIBP 11 | v4.8 12 | 512 13 | true 14 | true 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | AnyCPU 33 | false 34 | none 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 4 40 | 41 | 42 | AnyCPU 43 | pdbonly 44 | true 45 | bin\Release\ 46 | TRACE 47 | prompt 48 | 4 49 | 50 | 51 | 52 | 53 | 54 | true 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | False 76 | Microsoft .NET Framework 4.8 %28x86 and x64%29 77 | true 78 | 79 | 80 | False 81 | .NET Framework 3.5 SP1 82 | false 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /SharpHIBP/SharpHIBP.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | --------------------------------------------------------------------------------