345
|
1 //
|
|
2 // Copyright (C) 2014 by 510 Software Group
|
|
3 // licensed under the GPLv3 or later
|
|
4
|
|
5 package ch.ethz.ssh2.crypto;
|
|
6
|
346
|
7 import android.os.Build;
|
|
8 import android.os.Process;
|
|
9
|
|
10 import java.io.ByteArrayOutputStream;
|
|
11 import java.io.DataOutputStream;
|
|
12 import java.io.IOException;
|
|
13 import java.io.UnsupportedEncodingException;
|
345
|
14 import java.security.SecureRandom;
|
|
15
|
|
16
|
347
|
17 public class SecureRandomFix extends SecureRandom {
|
345
|
18
|
|
19 // http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html
|
|
20
|
|
21 private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
|
|
22 private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
|
|
23 getBuildFingerprintAndDeviceSerial();
|
|
24
|
|
25 private static byte[] generateReasonableSeed() {
|
|
26 try {
|
|
27 ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();
|
|
28 DataOutputStream seedBufferOut =
|
|
29 new DataOutputStream(seedBuffer);
|
|
30 seedBufferOut.writeLong(System.currentTimeMillis());
|
|
31 seedBufferOut.writeLong(System.nanoTime());
|
|
32 seedBufferOut.writeInt(Process.myPid());
|
|
33 seedBufferOut.writeInt(Process.myUid());
|
|
34 seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL);
|
|
35 seedBufferOut.close();
|
|
36 return seedBuffer.toByteArray();
|
|
37 } catch (IOException e) {
|
|
38 throw new SecurityException("Failed to generate seed", e);
|
|
39 }
|
|
40 }
|
|
41
|
|
42 /**
|
|
43 * Gets the hardware serial number of this device.
|
|
44 *
|
|
45 * @return serial number or {@code null} if not available.
|
|
46 */
|
|
47 private static String getDeviceSerialNumber() {
|
|
48 // We're using the Reflection API because Build.SERIAL is only available
|
|
49 // since API Level 9 (Gingerbread, Android 2.3).
|
|
50 try {
|
|
51 return (String) Build.class.getField("SERIAL").get(null);
|
|
52 } catch (Exception ignored) {
|
|
53 return null;
|
|
54 }
|
|
55 }
|
|
56
|
|
57 private static byte[] getBuildFingerprintAndDeviceSerial() {
|
|
58 StringBuilder result = new StringBuilder();
|
|
59 String fingerprint = Build.FINGERPRINT;
|
|
60 if (fingerprint != null) {
|
|
61 result.append(fingerprint);
|
|
62 }
|
|
63 String serial = getDeviceSerialNumber();
|
|
64 if (serial != null) {
|
|
65 result.append(serial);
|
|
66 }
|
|
67 try {
|
|
68 return result.toString().getBytes("UTF-8");
|
|
69 } catch (UnsupportedEncodingException e) {
|
|
70 throw new RuntimeException("UTF-8 encoding not supported");
|
|
71 }
|
|
72 }
|
|
73
|
|
74 public SecureRandomFix() {
|
|
75 super();
|
|
76 if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) {
|
|
77 // No need to apply the fix
|
|
78 return;
|
|
79 }
|
|
80 setSeed(generateReasonableSeed());
|
|
81 }
|
|
82 } |