Source Code Cross Referenced for NativePRNG.java in  » 6.0-JDK-Platform » solaris » sun » security » provider » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Platform » solaris » sun.security.provider 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package sun.security.provider;
027:
028:        import java.io.*;
029:
030:        import java.security.*;
031:        import java.security.SecureRandom;
032:
033:        /**
034:         * Native PRNG implementation for Solaris/Linux. It interacts with
035:         * /dev/random and /dev/urandom, so it is only available if those
036:         * files are present. Otherwise, SHA1PRNG is used instead of this class.
037:         *
038:         * getSeed() and setSeed() directly read/write /dev/random. However,
039:         * /dev/random is only writable by root in many configurations. Because
040:         * we cannot just ignore bytes specified via setSeed(), we keep a
041:         * SHA1PRNG around in parallel.
042:         *
043:         * nextBytes() reads the bytes directly from /dev/urandom (and then
044:         * mixes them with bytes from the SHA1PRNG for the reasons explained
045:         * above). Reading bytes from /dev/urandom means that constantly get
046:         * new entropy the operating system has collected. This is a notable
047:         * advantage over the SHA1PRNG model, which acquires entropy only
048:         * initially during startup although the VM may be running for months.
049:         *
050:         * Also note that we do not need any initial pure random seed from
051:         * /dev/random. This is an advantage because on some versions of Linux
052:         * it can be exhausted very quickly and could thus impact startup time.
053:         *
054:         * Finally, note that we use a singleton for the actual work (RandomIO)
055:         * to avoid having to open and close /dev/[u]random constantly. However,
056:         * there may me many NativePRNG instances created by the JCA framework.
057:         *
058:         * @since   1.5
059:         * @version 1.10, 05/05/07
060:         * @author  Andreas Sterbenz
061:         */
062:        public final class NativePRNG extends SecureRandomSpi {
063:
064:            private static final long serialVersionUID = -6599091113397072932L;
065:
066:            // name of the pure random file (also used for setSeed())
067:            private static final String NAME_RANDOM = "/dev/random";
068:            // name of the pseudo random file
069:            private static final String NAME_URANDOM = "/dev/urandom";
070:
071:            // singleton instance or null if not available
072:            private static final RandomIO INSTANCE = initIO();
073:
074:            private static RandomIO initIO() {
075:                Object o = AccessController
076:                        .doPrivileged(new PrivilegedAction() {
077:                            public Object run() {
078:                                File randomFile = new File(NAME_RANDOM);
079:                                if (randomFile.exists() == false) {
080:                                    return null;
081:                                }
082:                                File urandomFile = new File(NAME_URANDOM);
083:                                if (urandomFile.exists() == false) {
084:                                    return null;
085:                                }
086:                                try {
087:                                    return new RandomIO(randomFile, urandomFile);
088:                                } catch (Exception e) {
089:                                    return null;
090:                                }
091:                            }
092:                        });
093:                return (RandomIO) o;
094:            }
095:
096:            // return whether the NativePRNG is available
097:            static boolean isAvailable() {
098:                return INSTANCE != null;
099:            }
100:
101:            // constructor, called by the JCA framework
102:            public NativePRNG() {
103:                super ();
104:                if (INSTANCE == null) {
105:                    throw new AssertionError("NativePRNG not available");
106:                }
107:            }
108:
109:            // set the seed
110:            protected void engineSetSeed(byte[] seed) {
111:                INSTANCE.implSetSeed(seed);
112:            }
113:
114:            // get pseudo random bytes
115:            protected void engineNextBytes(byte[] bytes) {
116:                INSTANCE.implNextBytes(bytes);
117:            }
118:
119:            // get true random bytes
120:            protected byte[] engineGenerateSeed(int numBytes) {
121:                return INSTANCE.implGenerateSeed(numBytes);
122:            }
123:
124:            /**
125:             * Nested class doing the actual work. Singleton, see INSTANCE above.
126:             */
127:            private static class RandomIO {
128:
129:                // we buffer data we read from /dev/urandom for efficiency,
130:                // but we limit the lifetime to avoid using stale bits
131:                // lifetime in ms, currently 100 ms (0.1 s)
132:                private final static long MAX_BUFFER_TIME = 100;
133:
134:                // size of the /dev/urandom buffer
135:                private final static int BUFFER_SIZE = 32;
136:
137:                // In/OutputStream for /dev/random and /dev/urandom
138:                private final InputStream randomIn, urandomIn;
139:                private OutputStream randomOut;
140:
141:                // flag indicating if we have tried to open randomOut yet
142:                private boolean randomOutInitialized;
143:
144:                // SHA1PRNG instance for mixing
145:                // initialized lazily on demand to avoid problems during startup
146:                private volatile sun.security.provider.SecureRandom mixRandom;
147:
148:                // buffer for /dev/urandom bits
149:                private final byte[] urandomBuffer;
150:
151:                // number of bytes left in urandomBuffer
152:                private int buffered;
153:
154:                // time we read the data into the urandomBuffer
155:                private long lastRead;
156:
157:                // mutex lock for nextBytes()
158:                private final Object LOCK_GET_BYTES = new Object();
159:
160:                // mutex lock for getSeed()
161:                private final Object LOCK_GET_SEED = new Object();
162:
163:                // mutex lock for setSeed()
164:                private final Object LOCK_SET_SEED = new Object();
165:
166:                // constructor, called only once from initIO()
167:                private RandomIO(File randomFile, File urandomFile)
168:                        throws IOException {
169:                    randomIn = new FileInputStream(randomFile);
170:                    urandomIn = new FileInputStream(urandomFile);
171:                    urandomBuffer = new byte[BUFFER_SIZE];
172:                }
173:
174:                // get the SHA1PRNG for mixing
175:                // initialize if not yet created
176:                private sun.security.provider.SecureRandom getMixRandom() {
177:                    sun.security.provider.SecureRandom r = mixRandom;
178:                    if (r == null) {
179:                        synchronized (LOCK_GET_BYTES) {
180:                            r = mixRandom;
181:                            if (r == null) {
182:                                r = new sun.security.provider.SecureRandom();
183:                                try {
184:                                    byte[] b = new byte[20];
185:                                    readFully(urandomIn, b);
186:                                    r.engineSetSeed(b);
187:                                } catch (IOException e) {
188:                                    throw new ProviderException("init failed",
189:                                            e);
190:                                }
191:                                mixRandom = r;
192:                            }
193:                        }
194:                    }
195:                    return r;
196:                }
197:
198:                // read data.length bytes from in
199:                // /dev/[u]random are not normal files, so we need to loop the read.
200:                // just keep trying as long as we are making progress
201:                private static void readFully(InputStream in, byte[] data)
202:                        throws IOException {
203:                    int len = data.length;
204:                    int ofs = 0;
205:                    while (len > 0) {
206:                        int k = in.read(data, ofs, len);
207:                        if (k <= 0) {
208:                            throw new EOFException("/dev/[u]random closed?");
209:                        }
210:                        ofs += k;
211:                        len -= k;
212:                    }
213:                    if (len > 0) {
214:                        throw new IOException(
215:                                "Could not read from /dev/[u]random");
216:                    }
217:                }
218:
219:                // get true random bytes, just read from /dev/random
220:                private byte[] implGenerateSeed(int numBytes) {
221:                    synchronized (LOCK_GET_SEED) {
222:                        try {
223:                            byte[] b = new byte[numBytes];
224:                            readFully(randomIn, b);
225:                            return b;
226:                        } catch (IOException e) {
227:                            throw new ProviderException(
228:                                    "generateSeed() failed", e);
229:                        }
230:                    }
231:                }
232:
233:                // supply random bytes to the OS
234:                // write to /dev/random if possible
235:                // always add the seed to our mixing random
236:                private void implSetSeed(byte[] seed) {
237:                    synchronized (LOCK_SET_SEED) {
238:                        if (randomOutInitialized == false) {
239:                            randomOutInitialized = true;
240:                            randomOut = AccessController
241:                                    .doPrivileged(new PrivilegedAction<OutputStream>() {
242:                                        public OutputStream run() {
243:                                            try {
244:                                                return new FileOutputStream(
245:                                                        NAME_RANDOM, true);
246:                                            } catch (Exception e) {
247:                                                return null;
248:                                            }
249:                                        }
250:                                    });
251:                        }
252:                        if (randomOut != null) {
253:                            try {
254:                                randomOut.write(seed);
255:                            } catch (IOException e) {
256:                                throw new ProviderException("setSeed() failed",
257:                                        e);
258:                            }
259:                        }
260:                        getMixRandom().engineSetSeed(seed);
261:                    }
262:                }
263:
264:                // ensure that there is at least one valid byte in the buffer
265:                // if not, read new bytes
266:                private void ensureBufferValid() throws IOException {
267:                    long time = System.currentTimeMillis();
268:                    if ((buffered > 0) && (time - lastRead < MAX_BUFFER_TIME)) {
269:                        return;
270:                    }
271:                    lastRead = time;
272:                    readFully(urandomIn, urandomBuffer);
273:                    buffered = urandomBuffer.length;
274:                }
275:
276:                // get pseudo random bytes
277:                // read from /dev/urandom and XOR with bytes generated by the
278:                // mixing SHA1PRNG
279:                private void implNextBytes(byte[] data) {
280:                    synchronized (LOCK_GET_BYTES) {
281:                        try {
282:                            getMixRandom().engineNextBytes(data);
283:                            int len = data.length;
284:                            int ofs = 0;
285:                            while (len > 0) {
286:                                ensureBufferValid();
287:                                int bufferOfs = urandomBuffer.length - buffered;
288:                                while ((len > 0) && (buffered > 0)) {
289:                                    data[ofs++] ^= urandomBuffer[bufferOfs++];
290:                                    len--;
291:                                    buffered--;
292:                                }
293:                            }
294:                        } catch (IOException e) {
295:                            throw new ProviderException("nextBytes() failed", e);
296:                        }
297:                    }
298:                }
299:
300:            }
301:
302:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.