I need to get some data from X509 certificate.
If I open a certificate file in windows, its showing its serial number in this format.
ex. 39 65 70 eb d8 9f 28 20 4e c2 a0 6b 98 48 31 0d
The same data I am trying to obtain using java. After get it loaded, I use
x509.getSerialNumber();
and result is : 76292708057987193002565060032465481997
So what is the difference between both of these ? I want the result as upper one.
Windows shows the hexadecimal representation of the serial number, whereas Java returns a BigInteger result from X509Certificate.getSerialNumber().
To display the BigInteger as a hexadecimal value, just call toString(16).
BigInteger bi = new BigInteger("76292708057987193002565060032465481997");
System.out.println(bi.toString(16));
Will output:
396570ebd89f28204ec2a06b9848310d
The first one is hexadecimal value of the certificate.
The other one is decimal.
Now it depends on how you convert the initial certificate bytearray for printing it out.
Lets say this is your certificate:
byte[] cert = { (byte) 0xFD, (byte) 0xB1, (byte) 0xDD, ..., (byte) 0x00 };
BigInteger certVal = new BigInteger(cert);
System.out.println("And result is (hex): " + certVal.toString(16));
Related
This question already has answers here:
How to convert byte array to hex format in Java
(4 answers)
Closed 2 years ago.
So i have a piece of code, which converted byte[] from a binary file into int[] which then went on to be converted to String.
Example: 02 09 1A would translate to "2926" using String.valueOf(byte);
But this is where the fun begins: the old Code already split up the array before it became String so it didn't matter. Now i have code which needs to somehow figure out if there is a 2 9 or 29... How can i get the String to
- stay in Hex instead of "switching" to decimal and
- keep the zeros in the string
so i can always grab the next two chars, figure out which info they display and go on?
Input: 05 06 1D 11 07 08 01 32 21 28 2F 20 2E 21 34 22 25 33 01 02 09 0A FF 0B 0C 2!(/ .!4"%3
ΓΏ
Current Output: 562917781503340473246335234375112910-11112
Expected Output: 05061D110708013221282F202E21342225330102090AFF0B0C
(Didn't put my old code in here since it's based on int which is crap)
If I understand correctly, you have a byte[] as input, and you want to output a string that is all those bytes, in hex form, joined together:
private static String byteArrayToString(byte[] byteArray) {
StringBuilder builder = new StringBuilder();
for (byte b : byteArray) {
int i = Byte.toUnsignedInt(b);
if (i < 16) {
builder.append("0");
}
builder.append(Integer.toHexString(i).toUpperCase());
}
return builder.toString();
}
Note the use of Byte.toUnsignedInt. This converts things like -1 the byte to the int 0xff. This is required because Java's bytes are signed.
Also note where I pad with 0. I only do this if the byte is a single digit in hex. i < 16 is the condition to check this.
Another way:
char[] hexVals = {'0', '1','2','3','4','5','6','7','8','9','A', 'B','C','D','E','F'};
byte[] bytes = {5, 6, (byte)0xAB, (byte)0xde}; // sample input
char[] output = new char[bytes.length*2];
// split each byte's hex digits into two chars
for(int i=0; i < bytes.length; i++) {
output[2*i] = hexVals[(bytes[i] >> 4) & 0xf]; // HO nibble
output[2*i+1] = hexVals[bytes[i] & 0xf]; // LO nibble
}
System.out.println(new String(output)); // 0506ABDE
I have a normal String, I encode it using Base64 class from Java util and pass it in ECPublicKey constructor but its not working. Do we have to encode in some other format to pass it in ECPublicKey constructor?
I have tried creating keyfactory approach too, like below, the encoding obj is Base64-encoded String
byte[] keyBytesPublic = Base64.getDecoder().decode(encodingObj);
X509EncodedKeySpec specPublic = new X509EncodedKeySpec(keyBytesPublic);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
ECPublicKey public_key12 = (ECPublicKey) keyFactory.generatePublic(specPublic);
String obj = "{ "+
"hello world "+
"}";
byte[] encodingObj = Base64.getEncoder().encode(obj.getBytes());
byte[] keyBytesPublic = Base64.getDecoder().decode(encodingObj);
First tried generating from key fatory
X509EncodedKeySpec specPublic = new X509EncodedKeySpec(keyBytesPublic);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
ECPublicKey public_key12 = (ECPublicKey) keyFactory.generatePublic(specPublic);
PublicKey publicKey = keyFactory.generatePublic(specPublic);
or if i directly pass encoding obj in constructor
ECPublicKey publicKey1 = new ECPublicKeyImpl(encodingObj);
The format is called SubjectPublicKeyInfo, which is part of the X.509 specifications. It is an ASN.1 encoded structure that also includes the key type. Internally you would have an X9.63 structure encoding the public key. Within there you have the options of named curves (where curve parameters are identified using an OID) or curves specifying all of their parameters and uncompressed or compressed points for the public point W.
For instance, you can see an example using a named curve with OID and uncompressed public point in this other question I answered:
> openssl asn1parse -i -in ecpub.der -inform DER -dump
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
0000 - 00 04 d0 ee 64 61 7b 90-48 a2 a9 5f b5 a3 da 67 ....da{.H.._...g
0010 - 53 56 91 e0 cf 5b b8 85-3e 05 0c b9 e6 95 c3 8d SV...[..>.......
0020 - 26 ab d7 ee 47 94 38 61-1e cd 07 e6 90 0b 3d 4a &...G.8a......=J
0030 - 6a df c5 d5 9f f3 11 91-53 00 ff 0e 91 93 49 44 j.......S.....ID
0040 - 4c 58
Note that I changed the line to use DER as that's what Java is expecting. Java doesn't contain a PEM parser in the public API, you'll have to use e.g. Bouncy Castle for that.
You should not generate a key using a key factory from scratch, keys are part of a public / private key pair. To create such an encoding you can use the following code (including base64 if you need a string):
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(new ECGenParameterSpec("secp256r1"));
KeyPair kp = kpg.generateKeyPair();
ECPublicKey publicKey = (ECPublicKey) kp.getPublic();
System.out.println("Encoding format: " + publicKey.getFormat());
byte[] derEncoded = publicKey.getEncoded();
// base64 encoded is what you get for PEM, between the header and footer lines
String base64DEREncoded = Base64.getEncoder().encodeToString(derEncoded);
System.out.println("Base64 SubjectPublicKeyInfo: " + base64DEREncoded);
Result:
Encoding format: X.509
Base64 SubjectPublicKeyInfo: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDA0qMRpJwaJyJ4YDciMqWefvr/mwYvF1fKnblJl5DOqAh5XUXkdWvYRDTTs9hPoHfPaNWWC9I0hOGb6+JPNxVw==
Of course, you generally want to store the private key somewhere secure as well, e.g. in a key store.
I want to set the current time as the major and minor values of a beacon. Lets suppose this is the current time 1465398279009. I want 9827 to be the value of the major and 9009 the value of the minor. I use a java code to call the shell script. this is my java code
Long millis = System.currentTimeMillis();
String time=Long.toString(millis);
// String major1=time.substring(...);
String major1="99";
String major2="99";
String minor1="99";
String minor2="99";
ProcessBuilder pb2=new ProcessBuilder("/test.sh");
pb2.environment().put("major1", major1);
pb2.environment().put("major2", major2);
pb2.environment().put("minor1", minor1);
pb2.environment().put("minor2", minor2);
Process script_exec = pb2.start();
and this is the content of test.sh
sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d sd fh fb 33 j2 k9 j9 23 h2 n9 g7 v7 $param1 $major1 $major2 $minor1 $minor2 c5 00
In this example I just try to put both values to 9999 and 9999, but I get 39321 as result, I think the values are converted to big endian. I get confused and I don't understand well in which type and how shall I convert the String.
Long.toString can take two parameters. The first parameter is the number and the second parameter is the radix of the conversion.
Using a radix of 16 (Long.toString(millis, 16)) would result in a standard hexstring using [1-9a-f].
Try this:
String major1 = String.format("%02X", (millis >> 32) & 0xff);
String major2 = String.format("%02X", (millis >> 16) & 0xff);
String minor1 = String.format("%02X", (millis >> 8) & 0xff);
String minor2 = String.format("%02X", millis & 0xff);
The code above accesses each byte out of the timestamp and assigns it to the proper field, then formats it as a two character (one byte) hex number. A two character hex number is what you want for the script.
I am implementing RSA decryption. I have tried lot more things regarding RSA decryption and i have develop below code snipet.
public class AsymmetricEncryptionWithRSA {
public void decryptdata1(){
String PRIVATE_RSA_KEY_PKCS8 =
"-----BEGIN PRIVATE KEY-----\n" +
"<RSAKeyValue><Modulus>rotP8p9dJpRM/D7HHW9wsRWJEBVdZolRR0PuYGp/Mjae2gElTZSBQ44ifOvVquI95ECDa2ypIrEz1k/mKRtHPmsSMqmySWL9CVsEZAc/zNfYjIKb4BDaFiBaPEsboebIEuaN3NFt2bbl/RB45TCycYylgDjCdFFASRbHs0jX4cM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>\n" +
"-----END PRIVATE KEY-----\n";
String key = PRIVATE_RSA_KEY_PKCS8
.replace("-----BEGIN PRIVATE KEY-----\n", "")
.replace("\n-----END PRIVATE KEY-----\n", "");
System.out.println("key : "+key);
PKCS8EncodedKeySpec keySpec =
new PKCS8EncodedKeySpec(DatatypeConverter.parseBase64Binary(key));
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
String s = "kjZzSUPJBY4rM23P7t47W3RYPTqhEARCqOcgRfxxBSc3O2mxQZKE/HKDN9OzW5pc3K37rcd+Dc/d55uNJcJUWwmZL0vVgrQIBkQdSkrzcpXV9JD80Qgy8sCuHoqMU49U6I34I43+NUAFmQDkApHbMA8LGV6KLtoyIyUSpDiuW8Q=";
byte[] ciphertextBytes = Base64.decode(s.getBytes());
byte[] decryptedData = cipher.doFinal(ciphertextBytes);
String decryptedString = new String(decryptedData);
System.out.println("decrypted (plaintext) = " + decryptedString);
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
AsymmetricEncryptionWithRSA ae = new AsymmetricEncryptionWithRSA();
ae.decryptdata1();
}
}
But the above code ran into the following error:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=11, too big.
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at decrypttest.AsymmetricEncryptionWithRSA.decryptdata1(AsymmetricEncryptionWithRSA.java:189)
at decrypttest.AsymmetricEncryptionWithRSA.main(AsymmetricEncryptionWithRSA.java:210)
Caused by: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=11, too big.
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source)
at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source)
... 4 more
Crypto is frequently misunderstood, and thus I've decided to post a negative answer here. It's not very exciting, but if somebody finds themselves in scenario similar to the OPs they should probably be told why it can't work as early as possible in the process.
There are two possibilities when presented with a problem like this.
OP understands the problem correctly and they've been instructed to decrypt something with the public key.
or
OP does not completely understand their task but have been given a public key and some data and they need to make some progress with it.
For #1, it's simple: You can't decrypt RSA-encrypted data using a public key. It turns out the OP has only an RSA public key here, provided in an XML format. There's no way to reformat, massage, or otherwise fix up the public key to make it into the private key needed to decrypt the message. If this were doable then RSA would be trivially weak.
Now for #2, we have to step back and think of what might be true. We often find question askers here on stack overflow referring to "encrypting with the private key" in a context that inevitably implies that they really have an instance of an RSA signature. Rather than encryption, for clarity this should be called signing. An RSA signature is generated using the private key, and then everyone can verify the signature using the public key.
Now to verify the signature you also need the data that was signed, though there are some uncommon RSA signature schemes that allow for "message recovery". Since we have no data in this question, we have to try to go through the steps of verifying an RSA signature until we can make no more progress.
So we convert the XML data into an RSA modulus and public exponent. They are:
modulus
n = 122569097529914546498069291857337865246611656055620489010618854241554260593577609267786261511762266943671570032800601669006596562960007716726461943599993657820822102674379936038822313418546881231271467615708966752462196756466881703206510681054434799028982952649926637620598591790584184591371562810823451075011
and public exponent
e = 65537
The next step is to convert the signature string s into an integer. Using base64 decoding and the treating the result byte as big-endian integer I get:
sig = 102674047248928745858859342743181557926563805477311756100001889942342552706930945260621737497972422939132498975770606253415531107828422537100810225687174208681096157106683665614198008538708912251973616331643319025696474841958268570965587969021816350210845541576380037736081469197294740984924898949880343321540
And now I compute compute plain = sige mod n and get:
plain = 18281761513910757613247127600811463135393884768551021193363621715044011507027712128790112174797966270576132751506458211850250035395641481824697193105741034925363331241318624392861667609810000005509535564907655043671685464003456777077702725291701153287408411076758261166861253557068704213449855094306290667395
and finally convert plain to bytes using big endian to get:
92 36 73 49 43 c9 05 8e 2b 33 6d cf ee de 3b 5b 74 58 3d 3a a1 10 04 42 a8 e7 20 45 fc 71 05 27 37 3b 69 b1 41 92 84 fc 72 83 37 d3 b3 5b 9a 5c dc ad fb ad c7 7e 0d cf dd e7 9b 8d 25 c2 54 5b 09 99 2f 4b d5 82 b4 08 06 44 1d 4a 4a f3 72 95 d5 f4 90 fc d1 08 32 f2 c0 ae 1e 8a 8c 53 8f 54 e8 8d f8 23 8d fe 35 40 05 99 00 e4 02 91 db 30 0f 0b 19 5e 8a 2e da 32 23 25 12 a4 38 ae 5b c4
And ... nothing. It looks random to me, I see no patterns at all, nothing that looks like any possible version of PKCS#1 padding including PSS, nothing that looks like a 'message recovery' format.
So I can't solve this, none of the obvious things to try yield anything. It may be that the OP has been given an RSA-encrypted message but only given a public key, or maybe this is one of those RSA capture-the-flag exercises for which there is some weakness that allows for factoring the modulus, or maybe the public key is wrong. Or maybe I've made a mistake.
How to convert ASCII to hexadecimal values in java.
For example:
ASCII: 31 32 2E 30 31 33
Hex: 12.013
You did not convert ASCII to hexadecimal value. You had char values in hexadecimal, and you wanted to convert it to a String is how I'm interpreting your question.
String s = new String(new char[] {
0x31, 0x32, 0x2E, 0x30, 0x31, 0x33
});
System.out.println(s); // prints "12.013"
If perhaps you're given the string, and you want to print its char as hex, then this is how to do it:
for (char ch : "12.013".toCharArray()) {
System.out.print(Integer.toHexString(ch) + " ");
} // prints "31 32 2e 30 31 33 "
You can also use the %H format string:
for (char ch : "12.013".toCharArray()) {
System.out.format("%H ", ch);
} // prints "31 32 2E 30 31 33 "
It's not entirely clear what you are asking, since your "hex" string is actually in decimal. I believe you are trying to take an ASCII string representing a double and to get its value in the form of a double, in which case using Double.parseDouble should be sufficient for your needs. If you need to output a hex string of the double value, then you can use Double.toHexString. Note you need to catch NumberFormatException, whenever you invoke one of the primitive wrapper class's parse functions.
byte[] ascii = {(byte)0x31, (byte)0x32, (byte)0x2E, (byte)0x30, (byte)0x31, (byte)0x33};
String decimalstr = new String(ascii,"US-ASCII");
double val = Double.parseDouble(decimalstr);
String hexstr = Double.toHexString(val);