Подпись URL-схемы ключом доступа
Чтобы пользователи вашего приложения или сайта не сталкивались с ограничениями при запуске мобильного приложения Яндекс Карты:
-
Получите ключ-доступа. Для этого заполните форму.
-
Используйте URL следующего формата:
yandexmaps://maps.yandex.ru/?{параметры}&client=<идентификатор клиента>&signature=<подпись>
- client
- Идентификатор клиента, который вы получаете вместе с ключом. Даже если у вас несколько приложений, потребуется только один идентификатор.
- signature
- Подпись — это строка, которую нужно сформировать из исходного URL с помощью ключа доступа.
Как сформировать URL с подписью
-
Составьте URL, соответствующий задаче, которую должно выполнить приложение. Следующий URL позволяет показать точку на карте:
yandexmaps://maps.yandex.ru?ll=55.75,37.64&z=14
-
Добавьте к URL параметр
client
, в качестве значения укажите идентификатор:yandexmaps://maps.yandex.ru?ll=55.75,37.64&z=14&client=007
-
Вычислите хэш-сумму от URL, полученного на предыдущем шаге, с помощью хеш-функции SHA-256. Затем зашифруйте полученную хэш-сумму с помощью ключа доступа.
Ключ доступа — это RSA-ключ, который вы получаете после регистрации. Физически это запись в текстовом файле. Называться файл может, например, так:
key.pem
.Ниже приведен пример шифрования с помощью утилиты OpenSSL.
Bash
$ echo -n 'yandexmaps://maps.yandex.ru?ll=55.75,37.64&z=14&client=007' | openssl dgst -sha256 -sign key.pem | base64 | tr -d '\n' | python -c "import urllib, sys; print urllib.quote(sys.stdin.read(), safe='')"
-
Сформируйте US-ASCII строку подписи.
Чтобы передать двоичные данные в URL, их нужно перекодировать в набор символов US-ASCII. Поэтому сначала из двоичных данных сформируйте строку ASCII символов, используя base64-представление. Затем перекодируйте полученную строку в US-ASCII, используя механизм кодирования URL.
Python
from Crypto.PublicKey import RSA from Crypto.Hash import SHA256 from Crypto.Signature import PKCS1_v1_5 from base64 import b64encode from urllib import quote print "sign" with open("key.pem") as f: private_key = RSA.importKey(f.read()) h = SHA256.new(src_data) print "hash value" print h.hexdigest() signer = PKCS1_v1_5.new(private_key) signature = quote(b64encode(signer.sign(h)), safe='')
-
Используйте строку, полученную на предыдущем шаге, в качестве значения параметра
signature
. Пример URL с подписью:yandexmaps://maps.yandex.ru?ll=55.75,37.64&z=14&client=007&signature=JYEYuBc7154%2Be%2BHHW8RKG0O2dVx%2B%2B...
Как конвертировать RSA-ключ
Мы генерируем RSA-ключи в формате PEM (стандарт PKCS1). В мобильных операционных системах используются и другие форматы. Чтобы обеспечить совместимость, выполните конвертацию.
Примеры конвертации с помощью утилиты OpenSSL приведены ниже.
Конвертация текстового PEM-файла в бинарный DER. В результате получим ключ в формате DER (стандарт PKCS1):
$ openssl rsa -in key.pem -out key.der -outform DER
Конвертация PEM-ключа PKCS1 в ключ PKCS8:
$ openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in key-pkcs1.pem -out key-pkcs8.pem
Конвертация PEM-ключа PKCS1 в ключ в формате DER (стандарт PKCS8):
$ openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in key-pkcs1.pem -out key-pkcs8.pem
$ openssl pkcs8 -topk8 -inform PEM -outform DER -in key-pkcs8.pem -out key.der -nocrypt
Примеры кода нативных приложений
import android.content.Intent;
import android.net.Uri;
import android.util.Base64;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
public class YaMapsStarter {
private final String PRIVATE_KEY;
// Формирует подпись с помощью ключа.
public String sha256rsa(String key, String data) throws SecurityException {
String trimmedKey = key.replaceAll("-----\\w+ PRIVATE KEY-----", "")
.replaceAll("\\s", "");
try {
byte[] result = Base64.decode(trimmedKey, Base64.DEFAULT);
KeyFactory factory = KeyFactory.getInstance("RSA");
EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(result);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(factory.generatePrivate(keySpec));
signature.update(data.getBytes());
byte[] encrypted = signature.sign();
return Base64.encodeToString(encrypted, Base64.NO_WRAP);
} catch (Exception e) {
throw new SecurityException("Error calculating cipher data. SIC!");
}
}
// Формирует URI с подписью и запускает Яндекс Карты.
public void openMap() {
Uri uri = Uri.parse("yandexmaps://maps.yandex.ru").buildUpon()
.appendQueryParameter("ll", 55.75,37.64)
.appendQueryParameter("z", "14")
.appendQueryParameter("client", "007").build();
uri = uri.buildUpon()
.appendQueryParameter("signature", sha256rsa(PRIVATE_KEY, uri.toString()))
.build();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setPackage("ru.yandex.yandexmaps");
startActivity(intent);
}
}
Идентификатор клиента, который вы получаете вместе с ключом. Даже если у вас несколько приложений, потребуется только один идентификатор.
Ключ доступа — это RSA-ключ, который вы получаете после регистрации. Физически это запись в текстовом файле. Называться файл может, например, так: key.pem
.
Идентификатор клиента, который вы получаете вместе с ключом. Даже если у вас несколько приложений, потребуется только один идентификатор.
Подпись — это строка, которую нужно сформировать из исходного URL с помощью ключа доступа.
Идентификатор клиента, который вы получаете вместе с ключом. Даже если у вас несколько приложений, потребуется только один идентификатор.
Подпись — это строка, которую нужно сформировать из исходного URL с помощью ключа доступа.