├── 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 |
--------------------------------------------------------------------------------