Следующий код превращает открытый ключ, закодированный в PKCS # 1, в открытый ключ, закодированный в SubjectPublicKeyInfo, который является кодировкой открытого ключа, принятой RSA KeyFactory
с использованием X509EncodedKeySpec
, поскольку SubjectPublicKeyInfo определено в спецификациях X.509.
По сути, это низкоуровневая схема кодирования DER, которая
0x03
, и кодирование для количества неиспользуемых битов, byte-value 0x00
); 0x30
). Библиотеки не используются. На самом деле, для createSubjectPublicKeyInfoEncoding
операторы импорта даже не требуются.
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class PKCS1ToSubjectPublicKeyInfo {
private static final int SEQUENCE_TAG = 0x30;
private static final int BIT_STRING_TAG = 0x03;
private static final byte[] NO_UNUSED_BITS = new byte[] { 0x00 };
private static final byte[] RSA_ALGORITHM_IDENTIFIER_SEQUENCE =
{(byte) 0x30, (byte) 0x0d,
(byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01,
(byte) 0x05, (byte) 0x00};
public static RSAPublicKey decodePKCS1PublicKey(byte[] pkcs1PublicKeyEncoding)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
byte[] subjectPublicKeyInfo2 = createSubjectPublicKeyInfoEncoding(pkcs1PublicKeyEncoding);
KeyFactory rsaKeyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey generatePublic = (RSAPublicKey) rsaKeyFactory.generatePublic(new X509EncodedKeySpec(subjectPublicKeyInfo2));
return generatePublic;
}
public static byte[] createSubjectPublicKeyInfoEncoding(byte[] pkcs1PublicKeyEncoding)
{
byte[] subjectPublicKeyBitString = createDEREncoding(BIT_STRING_TAG, concat(NO_UNUSED_BITS, pkcs1PublicKeyEncoding));
byte[] subjectPublicKeyInfoValue = concat(RSA_ALGORITHM_IDENTIFIER_SEQUENCE, subjectPublicKeyBitString);
byte[] subjectPublicKeyInfoSequence = createDEREncoding(SEQUENCE_TAG, subjectPublicKeyInfoValue);
return subjectPublicKeyInfoSequence;
}
private static byte[] concat(byte[] ... bas)
{
int len = 0;
for (int i = 0; i < bas.length; i++)
{
len += bas[i].length;
}
byte[] buf = new byte[len];
int off = 0;
for (int i = 0; i < bas.length; i++)
{
System.arraycopy(bas[i], 0, buf, off, bas[i].length);
off += bas[i].length;
}
return buf;
}
private static byte[] createDEREncoding(int tag, byte[] value)
{
if (tag < 0 || tag >= 0xFF)
{
throw new IllegalArgumentException("Currently only single byte tags supported");
}
byte[] lengthEncoding = createDERLengthEncoding(value.length);
int size = 1 + lengthEncoding.length + value.length;
byte[] derEncodingBuf = new byte[size];
int off = 0;
derEncodingBuf[off++] = (byte) tag;
System.arraycopy(lengthEncoding, 0, derEncodingBuf, off, lengthEncoding.length);
off += lengthEncoding.length;
System.arraycopy(value, 0, derEncodingBuf, off, value.length);
return derEncodingBuf;
}
private static byte[] createDERLengthEncoding(int size)
{
if (size <= 0x7F)
{
// single byte length encoding
return new byte[] { (byte) size };
}
else if (size <= 0xFF)
{
// double byte length encoding
return new byte[] { (byte) 0x81, (byte) size };
}
else if (size <= 0xFFFF)
{
// triple byte length encoding
return new byte[] { (byte) 0x82, (byte) (size >> Byte.SIZE), (byte) size };
}
throw new IllegalArgumentException("size too large, only up to 64KiB length encoding supported: " + size);
}
public static void main(String[] args) throws Exception
{
// some weird 617 bit key, which is way too small and not a multiple of 8
byte[] pkcs1PublicKeyEncoding = Base64.getDecoder().decode("MFUCTgF/uLsPBS13Gy7C3dPpiDF6SYCLUyyl6CFqPtZT1h5bwKR9EDFLQjG/kMiwkRMcmEeaLKe5qdj9W/FfFitwRAm/8F53pQw2UETKQI2b2wIDAQAB");
RSAPublicKey generatePublic = decodePKCS1PublicKey(pkcs1PublicKeyEncoding);
System.out.println(generatePublic);
}
}
Примечания:
NoSuchAlgorithmException
, вероятно, следует отловить и поместить в RuntimeException
; createDERLengthEncoding
вероятно, не следует принимать отрицательные размеры. createDERLengthEncoding
для них - я предполагаю, что это работает, но лучше быть в безопасности, чем потом сожалеть. Вы хотите использовать Win32 Hooks. В частности, крючок клавиатуры.
Вы можете прочитать больше об этом здесь
Тип хука, который вам нужен - WH_KEYBOARD, и вы можете установить его через Win32 API SetWindowsHookEx.
По сути, windows будет вызывать функцию в dll, которую вы создадите, каждый раз, когда нажата клавиша в любом приложении в масштабах всей системы.
Хук будет вызывать вашу функцию, которая будет иметь такой интерфейс:
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
);
Подробнее об этом обратном вызове здесь.
С помощью windows hooks вы можете не только отслеживать общесистемные события во всех процессах, но и фильтровать их, а также полностью останавливать.
Посмотрите на хуки, которые можно установить с помощью SetWindowHookEx:
http://msdn.microsoft.com /en-us/library/ms644990(VS.85).aspx
Однако, если вы не используете "интерактивный" сервис, у вас не будет доступа к рабочему столу (и вы не должны запускать интерактивный сервис потому что это не будет работать правильно в новых версиях Windows). Чтобы получить доступ к рабочему столу / консоли, вам нужно изучить API управления сеансом и рабочим столом.
Проверьте Необработанный Вход API в MSDN:
http://msdn.microsoft.com/en-us/library/ms645536 (По сравнению с 85) .aspx
Это позволяет Вам быть введенными с клавиатур (среди прочего), не бездельничая с глобальными рычагами. Глобальные рычаги должны только использоваться как последнее прибежище, поскольку они могут представить непреднамеренные последствия.
Единственный недостаток к использованию Необработанного Входа состоит в том, что это не может правильно получить нажатия клавиш, которые сгенерированы программным обеспечением.