Related
I'm trying to display ASCII characters in my JTextPanel, but it doesn't work for a few extended characters like ASCII 217, ASCII 180, and the up arrow that I didn't find in the ASCII table.
I read a file from the file system with ASCII characters, and let's say for the moment that my problem is to display the file content. For the characters above, a blank space is displayed instead.
I already tried all the available charsets from Charset.availableCharsets(), and several fonts.
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame();
frame.setTitle("test");
frame.setBounds(100, 100, 900, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Container contentPane = frame.getContentPane();
JTextPane panel = new JTextPane();
contentPane.add(panel);
JFileChooser fileChooser = new JFileChooser();
if ( fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION ) {
File selectedFile = fileChooser.getSelectedFile();
InputStream in = new FileInputStream(selectedFile);
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.ISO_8859_1);
BufferedReader buffer = new BufferedReader(reader);
String s = null;
if ((s = buffer.readLine()) != null) {
panel.setText(s);
}
}
}
see we.tl/t-4hf9pgcsEZ (with https) to download a test file
here is the content of the file:
À¹ëÉÃN§T´jtkDÄ´†ê]":2q'6u$Q!44à!
®
When I past the content here in the 'edit question window' I see clearly the characters, but when I save my edits, many characters disapear... maybe a clue of the problem I'm facing
file converted in hexa with an online tool :
0xC0, 0xB9, 0xEB, 0xC9, 0xC3, 0x04, 0x4E, 0xA7, 0x54, 0xB4, 0x6A, 0x74, 0x6B, 0x44, 0xC4, 0x18,
0xB4, 0x17, 0x86, 0xEA, 0x5D, 0x22, 0x3A, 0x32, 0x17, 0x12, 0x13, 0x71, 0x27, 0x11, 0x36, 0x75,
0x24, 0x51, 0x21, 0x34, 0x34, 0x10, 0x14, 0xE0, 0x21, 0x02, 0x0E, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x0F, 0x00, 0x00, 0xAE,
I have an issue with a SecKeyRef generated on iOS device - when trying to use it on Java server, the exception is thrown:
InvalidKeyException: EC domain parameters must be encoded in the algorithm identifier
here's the code snippet from the server code:
String key = ...
byte[] byteKey = Base64.decode(key.getBytes(StandardCharsets.UTF_8));
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
KeyFactory kf = KeyFactory.getInstance("EC");
return kf.generatePublic(X509publicKey);
The exception is thrown by kf.generatePublic(X509publicKey);
The key is created on iOS, using SecKeyGeneratePair
[keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeEC forKey:(__bridge id)kSecAttrKeyType];
[keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:256] forKey:(__bridge id)kSecAttrKeySizeInBits];
// Set the private key dictionary
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[privateKeyAttr setObject:self.privateTag forKey:(__bridge id)kSecAttrApplicationTag];
// Set the public key dictionary
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[publicKeyAttr setObject:self.publicTag forKey:(__bridge id)kSecAttrApplicationTag];
// Set attributes to top level dictionary
[keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
[keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
// Generate key pair
OSStatus sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
The key pair is created successfully. I then extract key's bit data using following code
CFDataRef publicKeyBitsRef = NULL;
NSMutableDictionary *queryPublicKey = [NSMutableDictionary dictionary];
// Set the public key query dictionary.
[queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPublicKey setObject:self.publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeEC forKey:(__bridge id)kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnData];
// Get the key bits.
OSStatus sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyBitsRef);
Then, I export the key using CryptoExportImportManager
NSData *publicKeyIDERData = [manager exportPublicKeyToDER:keyBits keyType:(__bridge NSString*)kSecAttrKeyTypeEC keySize:256];
NSString *derKeyString = [publicKeyIDERData base64EncodedStringWithOptions:0];
According to this answer, the DER header contains info about key type and parameters and for secp256r1 key it's equivalent of following data
[
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00
]
Which is indeed added to key header on export.
derKeyString is then sent to backend and processed using Java code mentioned above. However, the exception is thrown.
The same backend processes also the key created on Android device using following code
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
keyPairGenerator.initialize(new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA256)
.setAlgorithmParameterSpec(
new ECGenParameterSpec("secp256r1"))
.setUserAuthenticationRequired(true).build());
keyPairGenerator.generateKeyPair();
The Android key works just fine.
What am I doing wrong? Have I forgotten about something while creating keys with SecKeyGeneratePair or exporting the public key?
I solved the problem, although I'm not sure why.
What I did is I ditched CryptoExportImportManager library and I'm manually creating key data, like so:
unsigned char _encodedECOID[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00
};
NSMutableData *data = [NSMutableData new];
[data appendBytes:_encodedECOID length:sizeof(_encodedECOID)];
[data appendData:keyBits]; // keyBits is od NSData type
Now the Java server properly creates public key from my string (base64 encoded from data).
However, having looked at source code of CryptoExportImportManager, the way it creates the encoded string from my key bits looks like that (in Swift):
let curveOIDHeader: [UInt8] = [0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00]
let curveOIDHeaderLen: Int = 26
var data = Data(bytes: curveOIDHeader, count: curveOIDHeaderLen)
data.append(rawPublicKeyBytes)
It basically does exactly the same thing. So where's the difference?
Now the only thing that comes to mind is the difference in how the header is stored - in my case it's an array of unsigned char, in library's case it's an array of UInt8.
According to this answer, C types unsigned char and uint8_t are not equivalent, they are only guaranteed to have the same length, but can differ in i.e. byte ordering.
Though that question had nothing to do with Swift's UInt8 (but was tagged C, of which Objective-C is superset), the documentation of Swift's UInt8 type says nothing about it's relation to unsigned char type, that would be the only reasonable explanation I can see.
I'm working on a card reader now. I want to take data from the card. I took uid. I want to take encrypted data. So I want to enter the secure mode and start session. I did something. I send a command apdu to start session but every time return unknown exception 0x1f here is the code.
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
terminal = terminals.get(0);
card = terminal.connect("T=1");
CardChannel channel = card.getBasicChannel();
byte[] c1 = { (byte) 0x80, (byte) 0x72, (byte) 0x80, (byte) 0x00, (byte) 0x18, (byte) 0x5c, (byte) 0xc5,
(byte) 0x0a, (byte) 0xa2, (byte) 0x5b, (byte) 0x38, (byte) 0x7f, (byte) 0x81, (byte) 0x3a, (byte) 0x3d,
(byte) 0x1a, (byte) 0x88, (byte) 0x7d, (byte) 0x26, (byte) 0xfc, (byte) 0x2b, (byte) 0xa8, (byte) 0xa7,
(byte) 0xdd, (byte) 0xdc, (byte) 0x71, (byte) 0xe0, (byte) 0xf3, (byte) 0xc6 };
ResponseAPDU response = channel.transmit(new CommandAPDU(0xFF, 0x00,0x00,0x00,c1,5,24));
This code returns me 6a81( it means function not supported),
if I send directly start session command(84 72 00 00) this time returns unknown exception.
Please help me. You don't have to find the error in code. Tell me How Can I Start Session in a Smart Card. I use HID OMNİKEY 5021 CL.
Exception in thread "main" javax.smartcardio.CardException: sun.security.smartcardio.PCSCException: Unknown error 0x1f
at sun.security.smartcardio.ChannelImpl.doTransmit(ChannelImpl.java:219)
at sun.security.smartcardio.ChannelImpl.transmit(ChannelImpl.java:90)
at CardReader.GetUID.getUID(GetUID.java:48)
at CardReader.GetUID.main(GetUID.java:86)
APDU you're sending is wrong, because you use CommandAPDU in an incorrect way.
new CommandAPDU(0xFF, 0x00,0x00,0x00,c1,5,24)
creates an APDU starting FF000000185CC50AA2... which is not what you (probably) want.
Try new CommandAPDU(0x84, 0x72,0x00,0x00,c1,5,24) instead.
See CommandAPDU javadoc and APDU format description.
I found the problem. The problem is byte types .net and java. C# byte type between 0 and 255 but java byte type -127 and +128. So if I send a higher than 127 value to java, card interpret like minus value.
I have a java card applet which will generate a RSA private public key pair (512 bits each). And it will send the public key modulus and exponent (modulus is 64 bytes)
In the host application (java) i need to re build the rsa public key using the same exponent and modulus, but when i try to reconstruct using the following code i am getting an error.
Java card code:
// this one to create the key pair
rsa_KeyPair = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_512);
rsa_KeyPair.genKeyPair();
rsa_PublicKey = (RSAPublicKey) rsa_KeyPair.getPublic();
rsa_PrivateCrtKey 0= (RSAPrivateCrtKey) rsa_KeyPair.getPrivate();
cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
//this is to send the modulus
byte[] buffer = apdu.getBuffer();
rsa_PublicKey.getModulus(buffer, ISO7816.OFFSET_CDATA);
apdu.setOutgoing();
apdu.setOutgoingLength((short) 64);
apdu.sendBytesLong(buffer, ISO7816.OFFSET_CDATA, (short) 64);
This part of the code is working fine. i am able to send the modulus perfectly to the host side.
Java code for host application below:
//command for retrieving modulus
resp = channel.transmit(new CommandAPDU(cmdMod));
BigInteger modulus = new BigInteger(resp.getData());
I am getting the 64 byte modulus as expected but when i make a big integer out of it its showing a large negative value.
//command for retrieving exponent
resp = channel.transmit(new CommandAPDU(cmdExp));
BigInteger modulus = new BigInteger(resp.getData());
byte[] input = { (byte) 0x92, (byte) 0x84, (byte) 0x3B,
(byte) 0xD3, (byte) 0x5D, (byte) 0x8A, (byte) 0x6B,
(byte) 0x56, (byte) 0xDA, (byte) 0xEA, (byte) 0xE0,
(byte) 0x2F, (byte) 0x6D, (byte) 0xAA, (byte) 0x62,
(byte) 0x4B, (byte) 0x38, (byte) 0xCE, (byte) 0xD4,
(byte) 0x70, (byte) 0xA2, (byte) 0x16, (byte) 0x35,
(byte) 0xCC, (byte) 0xEE, (byte) 0xB8, (byte) 0x31,
(byte) 0x13, (byte) 0x37, (byte) 0x40, (byte) 0xBE,
(byte) 0xA1, (byte) 0xCD, (byte) 0x84, (byte) 0xD9,
(byte) 0xF3, (byte) 0xE6, (byte) 0xCE, (byte) 0x26,
(byte) 0x0A, (byte) 0xC1, (byte) 0x40, (byte) 0xED,
(byte) 0x20, (byte) 0x8F, (byte) 0x3D, (byte) 0x9F,
(byte) 0x0D, (byte) 0xE7, (byte) 0x19, (byte) 0xC8,
(byte) 0x87, (byte) 0x96, (byte) 0x29, (byte) 0xF2,
(byte) 0x63, (byte) 0x34, (byte) 0x6D, (byte) 0x10,
(byte) 0xB9, (byte) 0xFB, (byte) 0xB4, (byte) 0x75,
(byte) 0xE9 };
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new RSAPublicKeySpec(modulus, exponent));
Cipher cipher = null;
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, pubKey);
byte[] cipherText = cipher.doFinal(input);
Error:
javax.crypto.BadPaddingException: Message is larger than modulus
at sun.security.rsa.RSACore.parseMsg(Unknown Source)
at sun.security.rsa.RSACore.crypt(Unknown Source)
at sun.security.rsa.RSACore.rsa(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:355)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
at testAuth.main(testAuth.java:150)
I checked the reponse from the card. i am getting all the 64 bytes of the modulus correctly. but when i make the Big Integer i am getting a large negative value. what should i do?
The issue is that BigInteger by default encodes to a signed big endian representation. If you decode the bytes using the constructor it does the opposite, i.e. it expects a signed value. Now most cryptography is performed on (large) unsigned integers. This is because the calculations are performed within a mathematical group (modulus calculations). These calculations are always performed on positive numbers, and RSA is no exception to this rule.
Now the size of the modulus is equal to the key size (not the key strength) of the RSA key. This means that an RSA key of 512 bit has a modulus of exactly 512 bits when encoded as a unsiged, big endian number. For numbers this means that the most significant bit is always set to '1'. However, that bit is used to indicate the sign bit for unsigned numbers encoded as a two-complement value. In other words, any modulus that has a key size dividable by 8 will be negative when interpreted as signed value.
The solution is of course to use the constructor where you can indicate the sign bit yourself:
BigInteger(int signum, byte[] magnitude)
where magnitude is the unsigned representation, in your case:
new BigInteger(1, resp.getData());
Java Card uses unsigned representations in the API, as it is more cryptographically oriented. No need for complicated methods in there.
Note that the reverse - creating a statically sized byte array out of an encoded signed BigInteger is even trickier, see this answer for information about how to perform that particular conversion.
I want to convert ANSI Escape sequence to IRC color sequence.
So I wrote a regular expression 1 \e\[([\d;]+)?m, however, shell_output_string.replaceFirst ("\\e\\[([\\d;]+)?m", "$1") will return both the matched substring and the rest of non-matched substrings.
Then I wrote regular expression 2 .*\e\[([\d;]+)?m.*, hope it can matches the whole string and replace it with the matched substring, however, replaceFirst (".*\\e\\[([\\d;]+)?m.*", "$1") returns empty string, but matches (".*\\e\\[([\\d;]+)?m.*") is true. What's wrong with this regular expression?
The following question is very similar to this question: Pattern/Matcher group() to obtain substring in Java?
Sample code
import java.util.regex.*;
public class AnsiEscapeToIrcEscape
{
public static void main (String[] args)
{
//# grep --color=always bot /etc/passwd
//
//bot:x:1000:1000:bot:/home/bot:/bin/bash
byte[] shell_output_array = {
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K (#1 - #11)
0x62, 0x6F, 0x74, // bot (#12 - #14)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#15 - #20)
0x3A, 0x78, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A, // :x:1000:1000: (#21 - #33)
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K (#34 - #44)
0x62, 0x6F, 0x74, // bot (#45 - #47)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#48 - #53)
0x3A, 0x2F, 0x68, 0x6F, 0x6D, 0x65, 0x2F, // :/home/ (#54 - #60)
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K (#61 - #71)
0x62, 0x6F, 0x74, // bot (#72 - #74)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#75 - #80)
0x3A, 0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x62, 0x61, 0x73, 0x68, // :/bin/bash (#81 - #90)
};
String shell_output = new String (shell_output_array);
System.out.println (shell_output);
System.out.println ("total " + shell_output_array.length + " bytes");
final String CSI_REGEXP = "\\e\\[";
final String CSI_SGR_REGEXP_First = CSI_REGEXP + "([\\d;]+)?m";
final String CSI_SGR_REGEXP = ".*" + CSI_SGR_REGEXP_First + ".*";
System.out.println (shell_output.replaceFirst(CSI_SGR_REGEXP_First, "$1"));
System.out.println (shell_output.replaceFirst(CSI_SGR_REGEXP, "$1"));
}
}
Regex's are greedy - that is, each pattern will try to match as much of the input as it can.
This means that when a pattern starts with .* , that part of the pattern will try to cover as much of the input text that it can - so effectively the forcing the remaining part of the pattern to try to find a match starting from the end of the input string working towards the front.
So, what's the first match for the rest of the pattern from the end of the string (or, if you prefer, what's the last substring that matches)? It's on the penultimate line of your input, and consists of just ^[m
That matches because the whole ([\d;]+) part of the pattern is made optional by the following ? .
In turn, this means that, since the final expression has no digits or ;, the $1 group is empty - hence you get empty string output.
At least, that's what I reckon without being near a Java machine to test it. Hope it helps.
The API of String's replaceFirst says :
replaceFirst
public String replaceFirst(String regex,
String replacement)
Replaces the first substring of this string that matches the given regular expression with the given replacement.
An invocation of this method of the form str.replaceFirst(regex, repl) yields exactly the same result as the expression
Pattern.compile(regex).matcher(str).replaceFirst(repl)
Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string; see Matcher.replaceFirst(java.lang.String). Use Matcher.quoteReplacement(java.lang.String) to suppress the special meaning of these characters, if desired.
Parameters:
regex - the regular expression to which this string is to be matched
replacement - the string to be substituted for the first match
Returns:
The resulting String
Throws:
PatternSyntaxException - if the regular expression's syntax is invalid
Since:
1.4
See Also:
Pattern
Please read the Note Part which specifies that the \ and $ may cause the result to be different.
You can use Pattern and Matcher instead.
Example
public class RegexMatches
{
public static void main( String args[] ){
// String to be scanned to find the pattern.
// String line = "This order was placed for QT3000! OK?";
// String pattern = "(.*)(\\d+)(.*)";
byte[] shell_output_array = {
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K (#1 - #11)
0x62, 0x6F, 0x74, // bot (#12 - #14)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#15 - #20)
0x3A, 0x78, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A, 0x31, 0x30, 0x30, 0x30, 0x3A, // :x:1000:1000: (#21 - #33)
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K (#34 - #44)
0x62, 0x6F, 0x74, // bot (#45 - #47)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#48 - #53)
0x3A, 0x2F, 0x68, 0x6F, 0x6D, 0x65, 0x2F, // :/home/ (#54 - #60)
0x1B, 0x5B, 0x30, 0x31, 0x3B, 0x33, 0x31, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[01;31m^[[K (#61 - #71)
0x62, 0x6F, 0x74, // bot (#72 - #74)
0x1B, 0x5B, 0x6D, 0x1B, 0x5B, 0x4B, // ^[[m^[[K (#75 - #80)
0x3A, 0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x62, 0x61, 0x73, 0x68, // :/bin/bash (#81 - #90)
};
String line = new String (shell_output_array);
//String pattern = "(.*)(\\d+)(.*)";
final String CSI_REGEXP = "\\e\\[";
final String CSI_SGR_REGEXP_First = CSI_REGEXP + "([\\d;]+)?m";
final String CSI_SGR_REGEXP = ".*" + CSI_SGR_REGEXP_First + ".*";
// Create a Pattern object
Pattern r = Pattern.compile(CSI_SGR_REGEXP);
// Now create matcher object.
Matcher m = r.matcher(line);
while (m.find()) {
System.out.println(m.start() + " " + m.end());
System.out.println("Found value: " + m.group());
}
}
}