New version for html code (#38)
* * Improved readability javascript * Added new styling based on bootstrap css (Only some css to make it readable for everyone) * Better responsive support * Some styling bug fixes * removed unnecessary comment Co-authored-by: Joshua Azimullah <j.r.azimullah@student.tudelft.nl>
This commit is contained in:
		
							parent
							
								
									cccf6ba8c0
								
							
						
					
					
						commit
						3777e4d9bd
					
				
							
								
								
									
										98
									
								
								html/essential_bootstrap.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								html/essential_bootstrap.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| /* took only the essential parts of the bootstrap css library to ensure that it is possible for everyone to read the code */ | ||||
| 
 | ||||
| body { | ||||
|     font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|     font-size: 14px; | ||||
|     line-height: 1.42857143; | ||||
|     color: #333333; | ||||
| } | ||||
| 
 | ||||
| p { | ||||
|     margin: 0 0 10px; | ||||
| } | ||||
| 
 | ||||
| a { | ||||
|     color: #337ab7; | ||||
|     text-decoration: none;   | ||||
| } | ||||
| 
 | ||||
| .form-control { | ||||
|     display: block; | ||||
|     width: 100%; | ||||
|     padding: 6px 12px; | ||||
|     font-size: 14px; | ||||
|     line-height: 1.42857143; | ||||
|     color: #555555; | ||||
|     background-color: #fff; | ||||
|     background-image: none; | ||||
|     border: 1px solid #ccc; | ||||
|     border-radius: 4px; | ||||
|     -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | ||||
|     box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | ||||
|     -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; | ||||
|     -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; | ||||
|     -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; | ||||
|     transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; | ||||
|     transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; | ||||
|     transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .btn { | ||||
|     display: inline-block; | ||||
|     margin-bottom: 0; | ||||
|     font-weight: normal; | ||||
|     text-align: center; | ||||
|     white-space: nowrap; | ||||
|     vertical-align: middle; | ||||
|     -ms-touch-action: manipulation; | ||||
|     touch-action: manipulation; | ||||
|     cursor: pointer; | ||||
|     background-image: none; | ||||
|     border: 1px solid transparent; | ||||
|     padding: 6px 12px; | ||||
|     font-size: 14px; | ||||
|     line-height: 1.42857143; | ||||
|     border-radius: 4px; | ||||
|     -webkit-user-select: none; | ||||
|     -moz-user-select: none; | ||||
|     -ms-user-select: none; | ||||
|     user-select: none; | ||||
| } | ||||
| 
 | ||||
| .btn-success { | ||||
|     color: #fff; | ||||
|     background-color: #5cb85c; | ||||
|     border-color: #4cae4c; | ||||
| } | ||||
| 
 | ||||
| button, html input[type="button"], input[type="reset"], input[type="submit"] { | ||||
|     -webkit-appearance: button; | ||||
|     cursor: pointer; | ||||
| } | ||||
| 
 | ||||
| button, select { | ||||
|     text-transform: none; | ||||
| } | ||||
| 
 | ||||
| button { | ||||
|     overflow: visible; | ||||
| } | ||||
| 
 | ||||
| button, input, optgroup, select, textarea { | ||||
|     color: inherit; | ||||
|     font: inherit; | ||||
|     margin: 0; | ||||
| } | ||||
| 
 | ||||
| *:before, *:after { | ||||
|     -webkit-box-sizing: border-box; | ||||
|     -moz-box-sizing: border-box; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
| 
 | ||||
| .form-inline .form-control { | ||||
|     display: inline-block; | ||||
|     width: auto; | ||||
|     vertical-align: middle; | ||||
| } | ||||
							
								
								
									
										308
									
								
								html/index.html
									
									
									
									
									
								
							
							
						
						
									
										308
									
								
								html/index.html
									
									
									
									
									
								
							| @ -1,166 +1,186 @@ | ||||
| <!DOCTYPE html> | ||||
| <!-- FYI must be serverd via HTTPS to function properly --> | ||||
| <html> | ||||
| <head> | ||||
| <meta charset='UTF-8'/> | ||||
|   <title>Pwned Password API lookup.</title> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1.0,  minimum-scale=1.0">   | ||||
| <style> | ||||
|   * { | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|   <head> | ||||
|     <meta charset='UTF-8'/> | ||||
|     <title>Pwned Password API lookup.</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0,  minimum-scale=1.0">   | ||||
|     <link rel="stylesheet" href="./essential_bootstrap.css"> | ||||
| 
 | ||||
|   html, body { | ||||
|    background-color:lightblue; | ||||
|    cursor:pointer; | ||||
|    height:100%; | ||||
|    width:100%; | ||||
|    padding:0; | ||||
|    margin:0; | ||||
|   } | ||||
|    | ||||
|   b { | ||||
|    color : red; | ||||
|   } | ||||
|    | ||||
|   #bodyDiv { | ||||
|     border:2px solid blue; | ||||
|     border-radius:7px; | ||||
|     height:150px; | ||||
|     width:600px; | ||||
|     margin:80px; | ||||
|     padding:25px; | ||||
|     background-color:darkgrey; | ||||
|     color:black; | ||||
|   } | ||||
|    | ||||
|    @media only screen and (max-width : 700px) { | ||||
|      | ||||
|    #bodyDiv { | ||||
|     border:2px solid blue; | ||||
|     border-radius:7px; | ||||
|     width:100%; | ||||
|     height:80%; | ||||
|     margin:0; | ||||
|     padding:25px; | ||||
|     background-color:darkgrey; | ||||
|     color:black; | ||||
|   } | ||||
|      | ||||
|    #hash { | ||||
|      font-size:10px; | ||||
|    }  | ||||
|      | ||||
|    } | ||||
|    | ||||
| </style> | ||||
| </head> | ||||
| <body> | ||||
| <div id="bodyDiv"> | ||||
| <span title="Password does not leave the browser, but it will show on the screen.">?</span> | ||||
| <input id="inPut" type="text" placeholder="Password..."> | ||||
| <button title="Click to send part of hashed password.">Check</button> | ||||
| <div> | ||||
|   <p id="outPut"></p> | ||||
| </div> | ||||
| 
 | ||||
| </div> | ||||
| <a href="https://github.com/mikepound/pwned-search">The inspiration!</a> | ||||
|   <script> | ||||
| let first = ""; | ||||
| let last = ""; | ||||
| let hash = ""; | ||||
| function hexString(buffer) { | ||||
|   // creates an array of 8-bit unsigned integers | ||||
|   const byteArray = new Uint8Array(buffer); | ||||
|   // turns that hash into hex | ||||
|   const hexCodes = [...byteArray].map(value => { | ||||
|     // eash element in array is converted to base 16 string | ||||
|     const hexCode = value.toString(16); | ||||
|     // pad beggining with 0  why? | ||||
|     const paddedHexCode = hexCode.padStart(2, '0'); | ||||
|     // return upper case hex hash | ||||
|     return paddedHexCode.toUpperCase(); | ||||
|   }); | ||||
|   // return a string not an array | ||||
|   return hexCodes.join(''); | ||||
| } | ||||
| 
 | ||||
| function digestMessage(message) { | ||||
|    // Returns a newly constructed TextEncoder that will generate a byte stream with utf-8 encoding. | ||||
|   const encoder = new TextEncoder();  | ||||
|    // Takes a USVString as input, and returns a Uint8Array containing utf-8 encoded text. | ||||
|   const data = encoder.encode(message); | ||||
|    // returns the hash | ||||
|    //The digest() method of the SubtleCrypto interface generates a digest of the given data.  | ||||
|    // A digest is a short fixed-length value derived from some variable-length input. | ||||
|   return window.crypto.subtle.digest('SHA-1', data); | ||||
| } | ||||
| 
 | ||||
| function runCheck() { | ||||
| let outPut = document.getElementById("outPut"); | ||||
| let inPut = document.getElementById("inPut"); | ||||
| let text = inPut.value; | ||||
| if (text === "") return false; | ||||
| inPut.value = ""; | ||||
|     <style> | ||||
| 
 | ||||
|        | ||||
| digestMessage(text).then(digestValue => { | ||||
|   hash = hexString(digestValue); | ||||
|   first = hash.substring(0, 5); | ||||
|   last = hash.substring(5); | ||||
|   fetch('https://api.pwnedpasswords.com/range/' + first) | ||||
|   .then( | ||||
|     function(response) { | ||||
|       if (response.status !== 200) { | ||||
|         console.log('Looks like there was a problem. Status Code: ' + | ||||
|           response.status); | ||||
|         return; | ||||
|       html, body { | ||||
|         background-color:lightblue; | ||||
|         height:100%; | ||||
|         width:100%; | ||||
|         padding:0; | ||||
|         margin:0; | ||||
|       } | ||||
|     return response.text(); | ||||
|   }) | ||||
|   .then(function(text) { | ||||
|     return text.split("\r\n");   | ||||
|   }) | ||||
|   .then(function(arr){ | ||||
| 
 | ||||
|      document.getElementById("outPut") | ||||
|           .innerHTML = "The password : " + text +  | ||||
|           "SHA1 Hash : " + hash +  | ||||
|           "<br>Was not found!"; | ||||
|       .source { | ||||
|         position: absolute; | ||||
|         margin: 15px; | ||||
|         margin-left: 0px; | ||||
|         bottom: 0; | ||||
|       } | ||||
|        | ||||
|      arr.forEach((s)=>{ | ||||
|       b { | ||||
|       color : red; | ||||
|       } | ||||
|        | ||||
|        let a = s.split(":"); | ||||
|       .bodyDiv { | ||||
|         position: relative; | ||||
|         border-radius:7px; | ||||
|         height:300px; | ||||
|         width:600px; | ||||
|         min-width:245px; | ||||
|         margin:80px; | ||||
|         padding:25px; | ||||
|         background-color: white; | ||||
|       } | ||||
| 
 | ||||
|        if(a[0] == last) { | ||||
|       div { | ||||
|         margin-top: 10px; | ||||
|       } | ||||
|        | ||||
|         document.getElementById("outPut") | ||||
|            .innerHTML = "The password : " + text +  | ||||
|            "<br>SHA1 Hash : <span id='hash'>" + hash +  | ||||
|            "</span><br>Was found <b>" + a[1] + "</b> times!"; | ||||
|       @media only screen and (max-width : 800px) { | ||||
|          | ||||
|         return true; | ||||
|         #hash { | ||||
|           font-size:10px; | ||||
|         } | ||||
| 
 | ||||
|        } | ||||
|         .bodyDiv { | ||||
|           position: fixed; | ||||
|           top: 0; | ||||
|           right: 0; | ||||
|           left: 0; | ||||
|           width: auto; | ||||
|           margin: 10px; | ||||
|         } | ||||
|          | ||||
|      }); | ||||
|       } | ||||
|        | ||||
|   }) | ||||
|   .catch(function(error) { | ||||
|     log('Request failed', error) | ||||
|   }); | ||||
|     </style> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div class="bodyDiv"> | ||||
|       <p>Only the first five characters of the hash of your password get send to <a href="https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange">haveibeenpwned.com</a></p> | ||||
|       <form class="form-inline" onsubmit="javascript:runCheck();return false;" > | ||||
|         <input id="input" class="form-control" type="text" placeholder="Password..."> | ||||
|         <button title="Click to send part of hashed password." class="btn btn-success" type="submit">Check</button> | ||||
|       </form>  | ||||
|       <div><p id="output"></p></div> | ||||
| 
 | ||||
| }); | ||||
|       <a class="source" href="https://github.com/mikepound/pwned-search">Source code on github</a> | ||||
|     </div> | ||||
|     <script> | ||||
| 
 | ||||
| outPut.value = ""; | ||||
|   let first = ""; | ||||
|   let last = ""; | ||||
|   let hash = ""; | ||||
| 
 | ||||
| } | ||||
|   function hexString(buffer) { | ||||
|     // creates an array of 8-bit unsigned integers | ||||
|     const byteArray = new Uint8Array(buffer); | ||||
|     // turns that hash into hex | ||||
|     const hexCodes = [...byteArray].map(value => { | ||||
|       // each element in array is converted to base 16 string | ||||
|       const hexCode = value.toString(16); | ||||
|       // pad beggining with 0  why? | ||||
|       const paddedHexCode = hexCode.padStart(2, '0'); | ||||
|       // return upper case hex hash | ||||
|       return paddedHexCode.toUpperCase(); | ||||
|     }); | ||||
|     // return a string not an array | ||||
|     return hexCodes.join(''); | ||||
|   } | ||||
| 
 | ||||
| document.querySelector("button") | ||||
|         .addEventListener("click", runCheck); | ||||
|   async function digestMessage(message) { | ||||
|     // Returns a newly constructed TextEncoder that will generate a byte stream with utf-8 encoding. | ||||
|     const encoder = new TextEncoder();  | ||||
|     // Takes a USVString as input, and returns a Uint8Array containing utf-8 encoded text. | ||||
|     const data = encoder.encode(message); | ||||
| 
 | ||||
|   </script> | ||||
| </body> | ||||
|     // returns the hash | ||||
|     // The digest() method of the SubtleCrypto interface generates a digest of the given data.  | ||||
|     // A digest is a short fixed-length value derived from some variable-length input. | ||||
|     return window.crypto.subtle.digest('SHA-1', data); | ||||
|   } | ||||
| 
 | ||||
|   async function runCheck() { | ||||
|      | ||||
|     // get references to the dom | ||||
|     let output = document.getElementById("output"); | ||||
|     let input = document.getElementById("input"); | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
|     try { | ||||
|       // extract input text from textbox | ||||
|       let text = input.value; | ||||
|       input.value = ""; | ||||
| 
 | ||||
| 
 | ||||
|       if (text === "") { | ||||
|         throw "Textbox can't be empty"; | ||||
|       } | ||||
| 
 | ||||
|       // generate hash buffer | ||||
|       let digestValue = await digestMessage(text); | ||||
| 
 | ||||
|        | ||||
| 
 | ||||
|       // turn buffer into string | ||||
|       hash = hexString(digestValue); | ||||
| 
 | ||||
|       // split hash into head and tail | ||||
|       first = hash.substring(0, 5); | ||||
|       last = hash.substring(5); | ||||
|       let response = await fetch('https://api.pwnedpasswords.com/range/' + first); | ||||
| 
 | ||||
|       // get response text | ||||
|       let responseText = await response.text(); | ||||
| 
 | ||||
|       // split the response into an array with potential passwords | ||||
|       let arr = responseText.split("\r\n");   | ||||
|        | ||||
|       // if nothing was found this will be displayed | ||||
|       document.getElementById("output") | ||||
|             .innerHTML = "The password : " + text +  | ||||
|             "<br>SHA1 Hash : <span id='hash'>" + hash +  | ||||
|             "</span><br>Was not found!"; | ||||
| 
 | ||||
|       arr.forEach((s)=>{ | ||||
|          | ||||
|         // split each line into the found hash and the amount of occurences | ||||
|         let a = s.split(":"); | ||||
|          | ||||
|         // a[0] is the found hash | ||||
|         if(a[0] === last) { | ||||
|            | ||||
|           // set output text | ||||
|           document.getElementById("output") | ||||
|             .innerHTML = "The password : " + text +  | ||||
|             "<br>SHA1 Hash : <span id='hash'>" + hash +  | ||||
|             "</span><br>Was found <b>" + a[1] + "</b> times!"; | ||||
|              | ||||
|           return;  | ||||
|         } | ||||
|          | ||||
|       }); | ||||
|     } catch (error) { | ||||
| 
 | ||||
|       // set error output  | ||||
|       document.getElementById("output").innerHTML = | ||||
|           "<b>" + error + "</b>"; | ||||
|     } | ||||
|      | ||||
|     output.value = ""; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     </script> | ||||
|   </body> | ||||
| </html> | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user