Преобразование Public Key в String и String в Public Key
ЧТО ДЕЛАЮ: Создаю Public Key, преобразую его в строку и записываю строку в JSON, в котором передаю на сервер, где принимаю скриптом php и сохраняю эту строку в blob mysql. Затем запрашиваю эту строку, получаю ее в виде параметра в json, преобразую в Public Key и проверяю с его помощью цифровую подпись.
В ЧЕМ ПРОБЛЕМА: Если убрать из списка этих действий запись в json, отправку на сервер и получение с сервера json, т.е. если преобразовать Public Key в строку, а потом преобразовать строку обратно в Public Key, то все работает нормально, но если сохраняю строку в json и потом получаю строку из json то выдается ошибка: "java.security.spec.InvalidKeySpecException: encoded key spec not recognized: y value does not appear to be in correct group".
КАК ДЕЛАЮ:
// Создание Public Key:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(2048);
KeyPair pair = keyGen.generateKeyPair();
publicKey = pair.getPublic();
privateKey = pair.getPrivate();
// Преобразование Public Key в массив байтов:
byte[] b = pub.getEncoded();
// Преобразование массива байтов в строку:
String s = byteArrayToString(b);
Далее передача строки s в виде параметра json на сервер, получение на сервере, сохранение скриптом php в blob mysql, затем запрос из клиента на сервер, получение строки из blob, запись в параметр json, получение json на клиенте, вынимание из json строки.
// Преобразование из строки в массив байтов:
byte[] b1 = stringToByte(s);
// Преобразование массива байтов в Public Key:
KeyFactory kf = KeyFactory.getInstance("DSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b1);
PublicKey pub1 = kf.generatePublic(publicKeySpec);
Далее - стандартная проверка цифровой подписи. Вот преобразования Public Key в строку и обратно:
// Преобразование массива байт (byte[]) в строку:
public static String byteArrayToString(byte[] bt) {
int dLength = bt.length;
// Выводим начальные значения:
String bitsString = "";
String result = "";
for(byte datum : bt) {
// преобразовать в биты:
bitsString = Integer.toBinaryString((int)datum);
// дополнить нулями до 8 символов:
// while(bitsString.length() < 8) {
// bitsString = "0" + bitsString;
// }
// поставить разделитель:
bitsString = bitsString + "-";
// добавить в общую строку:
result = result + bitsString;
}
return result;
}
// Преобразование строки в массив байт (byte[]):
public static byte[] stringToByte(String str) {
// Строку в массив:
String s;
int ind = 0;
// Определяем количество байт в полученной строке по количеству разделителей:
int colByte = countEntries(str, "-");
// Инициализируем байтовый массив по количеству байт:
byte[] b = new byte[colByte];
// Длина исходной строки:
int slength = str.length();
int j = 0;
while(ind < slength) {
// Индекс ближайшего разделителя:
ind = str.indexOf("-");
// Подстрока одного числа:
s = str.substring(0, ind);
//s1 = s1.replaceAll("[^0-9]", ""); // Убираем все символы кроме чисел.
str = str.substring(ind+1,slength); // получаем оставшийся кусок строки
slength = str.length();
// Преобразование из двоичной в десятичное число:
long i = Long.parseLong(s, 2); // Могут быть числа, большие диапазона int, поэтому используем long.
// Добавить в массив byte[]:
b[j] = (byte)i;
j++;
}
return b;
}
// Определение количества подписей по количеству разделителей (сколько раз подстрока subStr встречается в строке str):
public static int countEntries(String str, String subStr) {
return (str.length() - str.replace(subStr, "").length())/subStr.length();
}
ВОПРОС: что я делаю не так или в чем может быть дело?