⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 passwordmasker.java

📁 java 实现的签名方案
💻 JAVA
字号:
package it.trento.comune.j4sign.examples;import java.io.*;import java.util.*;/** * Class for securely read characters from the console without showing it.<br> * Note that Java does not support this feature natively; the code originally * appeared on a web forum: {<a href="http://forum.java.sun.com/thread.jspa?forumID=9&threadID=490728"> * http://forum.java.sun.com/thread.jspa?forumID=9&threadID=490728</a>)  */public class PasswordMasker extends Object {    public static void main(String[] args) throws Exception {        System.out.println(PasswordMasker                .readConsoleSecure("Enter password: "));    }/*** Reads and returns some sensitive piece of information (e.g. a password)* from the console (i.e. System.in and System.out) in a secure manner.* <p>* For top security, all console input is masked out while the user types in the password.* Once the user presses enter, the password is read via a call to {@link #readLineSecure readLineSecure(in)},* using a PushbackInputStream that wraps System.in.* <p>* This method never returns null.* <p>* @throws IOException if an I/O problem occurs* @throws InterruptedException if the calling thread is interrupted while it is waiting at some point* @see <a href="http://java.sun.com/features/2002/09/pword_mask.html">Password masking in console</a>*/    public static final char[] readConsoleSecure(String prompt)            throws IOException, InterruptedException {        System.out.println();        /*         * start a separate thread which will mask out all characters typed on         * System.in by overwriting them using System.out:         */        StreamMasker masker = new StreamMasker(System.out, prompt);        Thread threadMasking = new Thread(masker);        threadMasking.start();        /*         * Goal: block this current thread (allowing masker to mask all user         * input) while the user is in the middle of typing the password. This         * may be achieved by trying to read just the first byte from System.in,         * since reading from System.in blocks until it detects that an enter         * has been pressed. Wrap System.in with a PushbackInputStream because         * this byte will be unread below.         *          * Problem: Dependent on the operating system or java vm(?) there is a         * maximum number of bytes, which is buffered before enter is pressed.         * E.g. on Solaris 8.0, JDK 1.4.1 exactly 256 bytes are buffered. That         * means that no following return will be recognized to release the         * current Thread, then.         */        PushbackInputStream pin = new PushbackInputStream(System.in);        int b = pin.read();        /*         * When current thread gets here, the block on reading System.in is over         * (e.g. the user pressed enter, or some error occurred?) signal         * threadMasking to stop and wait till it is dead:         */        masker.stop();        threadMasking.join();        /*         * check for stream errors:         */        if (b == -1) {            throw new IOException(                    "end-of-file was detected in System.in without any "                            + "data being read");        }        if (System.out.checkError()) {            throw new IOException("an I/O problem was detected in System.out");        }        /*         * pushback the first byte and supply the now unaltered stream to         * readLineSecure which will return the complete password:         */        pin.unread(b);        return readLineSecure(pin);    }    /**	* Reads chars from in until an end-of-line sequence (EOL) or end-of-file (EOF) is encountered,	* and then returns the data as a char[].	* <p>	* The EOL sequence may be any of the standard formats: '\n' (unix), '\r' (mac), "\r\n" (dos).	* The EOL sequence is always completely read off the stream but is never included in the result.	* <i>Note:</i> this means that the result will never contain the chars '\n' or '\r'.	* In order to guarantee reading thru but not beyond the EOL sequence for all formats (unix, mac, dos),	* this method requires that a PushbackInputStream and not a more general InputStream be supplied.	* <p>	* The code is secure: no Strings are used, only char arrays,	* and all such arrays other than the result are guaranteed to be blanked out after last use to ensure privacy.	* Thus, this method is suitable for reading in sensitive information such as passwords.	* <p>	* This method never returns null; if no data before the EOL or EOF is read, a zero-length char[] is returned.	* <p>	* @throws IllegalArgumentException if in == null	* @throws IOException if an I/O problem occurs	* @see <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#PBEEx">Password based encryption code examples from JCE documentation</a>	*/    protected static final char[] readLineSecure(PushbackInputStream in)            throws IllegalArgumentException, IOException {        if (in == null) {            throw new IllegalArgumentException("in == null");        }        char[] buffer = null;        try {            buffer = new char[128];            boolean loop = true;            int offset = 0;            while (loop) {                int c = in.read();                switch (c) {                case -1:                case '\n':                    loop = false;                    break;                case '\r':                    int c2 = in.read();                    if ((c2 != '\n') && (c2 != -1)) {                        /*                         * guarantees that mac & dos line end sequences are                         * completely read thru but not beyond                         */                        in.unread(c2);                    }                    loop = false;                    break;                default:                    buffer = checkBuffer(buffer, offset);                    buffer[offset++] = (char) c;                    break;                }            }            char[] result = new char[offset];            System.arraycopy(buffer, 0, result, 0, offset);            return result;        } finally {            eraseChars(buffer);        }    }    /**	* Checks if buffer is sufficiently large to store an element at an index == offset.	* If it is, then buffer is simply returned.	* If it is not, then a new char[] of more than sufficient size is created and initialized with buffer's current elements and returned;	* the original supplied buffer is guaranteed to be blanked out upon method return in this case.	* <p>	* @throws IllegalArgumentException if buffer == null; offset < 0	*/    protected static final char[] checkBuffer(char[] buffer, int offset)            throws IllegalArgumentException {        if (buffer == null) {            throw new IllegalArgumentException("buffer == null");        }        if (offset < 0) {            throw new IllegalArgumentException("offset = " + offset + " is < 0");        }        if (offset < buffer.length) {            return buffer;        } else {            try {                char[] bufferNew = new char[offset + buffer.length];                System.arraycopy(buffer, 0, bufferNew, 0, buffer.length);                return bufferNew;            } finally {                eraseChars(buffer);            }        }    }    /** If buffer is not null, fills buffer with space (' ') chars. */    public static final void eraseChars(char[] buffer) {        if (buffer != null) {            Arrays.fill(buffer, ' ');        }    }    /**     * Masks an InputStream by overwriting blank characters to the PrintStream     * corresponding to its output. A typical application is for password input     * masking.     *      * @see <a href="http://java.sun.com/features/2002/09/pword_mask.html"     *      >Password masking in console </a>     */    public static class StreamMasker implements Runnable {        private static final String TEN_BLANKS = repeatChars(' ', 10);		private final PrintStream out;		private final String promptOverwrite;		private volatile boolean doMasking;	// MUST be volatile to ensure update by one thread is instantly visible to other threads 		/**		* Constructor.		* <p>		* @throws IllegalArgumentException if out == null; prompt == null; prompt contains the char '\r' or '\n'		*/		public StreamMasker(PrintStream out, String prompt) throws IllegalArgumentException {			if (out == null) throw new IllegalArgumentException("out == null");			if (prompt == null) throw new IllegalArgumentException("prompt == null");			if (prompt.indexOf('\r') != -1) throw new IllegalArgumentException("prompt contains the char '\\r'");			if (prompt.indexOf('\n') != -1) throw new IllegalArgumentException("prompt contains the char '\\n'"); 			this.out = out;			String setCursorToStart = repeatChars('\b', prompt.length() + TEN_BLANKS.length());			this.promptOverwrite =				setCursorToStart +    // sets cursor back to beginning of line:				prompt +              // writes prompt (critical: this reduces visual flicker in the prompt text that otherwise occurs if simply write blanks here)				TEN_BLANKS +          // writes 10 blanks beyond the prompt to mask out any input; go 10, not 1, spaces beyond end of prompt to handle the (hopefully rare) case that input occurred at a rapid rate				setCursorToStart +    // sets cursor back to beginning of line:				prompt;               // writes prompt again; the cursor will now be positioned immediately after prompt (critical: overwriting only works if all input text starts here)		}		/**		* Repeatedly overwrites the current line of out with prompt followed by blanks.		* This effectively masks any chars coming on out, as long as the masking occurs fast enough.		* <p>		* To help ensure that masking occurs when system is in heavy use, the calling thread will have its priority		* boosted to the max for the duration of the call (with its original priority restored upon return).		* Interrupting the calling thread will eventually result in an exit from this method,		* and the interrupted status of the calling thread will be set to true.		* <p>		* @throws RuntimeException if an error in the masking process is detected		*/		public void run() throws RuntimeException {			int priorityOriginal = Thread.currentThread().getPriority();			Thread.currentThread().setPriority(Thread.MAX_PRIORITY);			try {				doMasking = true;	// do this assignment here and NOT at variable declaration line to allow this instance to be restarted if desired				while (doMasking) {					out.print(promptOverwrite);						// call checkError, which first flushes out, and then lets us confirm that everything was written correctly:					if (out.checkError()) throw new RuntimeException("an I/O problem was detected in out");	// should be an IOException, but that would break method contract 						// limit the masking rate to fairly share the cpu; interruption breaks the loop					try {						Thread.currentThread().sleep(1);	// have experimentally found that sometimes see chars for a brief bit unless set this to its min value					}					catch (InterruptedException ie) {						Thread.currentThread().interrupt();	// resets the interrupted status, which is typically lost when an InterruptedException is thrown, as per our method contract; see Lea, "Concurrent Programming in Java Second Edition", p. 171						return;	// return, NOT break, since now want to skip the lines below where write bunch of blanks since typically the user will not have pressed enter yet					}				}					// erase any prompt that may have been spuriously written on the NEXT line after the user pressed enter				out.print('\r');				for (int i = 0; i < promptOverwrite.length(); i++) out.print(' ');				out.print('\r');			}			finally {				Thread.currentThread().setPriority(priorityOriginal);			}		}		/** Signals any thread executing run to stop masking and exit run. */		public void stop() { doMasking = false; }        /**    	* Returns a String of the specified length which consists of entirely of the char c.    	* <p>    	* @throws IllegalArgumentException if length < 0        */        public static final String repeatChars(char c, int length) throws IllegalArgumentException {    		if (length < 0) throw new IllegalArgumentException("length = " + length + " is < 0");         		StringBuffer sb = new StringBuffer(length);    		for (int i = 0; i < length; i++) {    			sb.append(c);    		}    		return sb.toString();    	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -