RSA — это алгоритм шифрования с открытым ключем. Шифрование с открытым ключем весьма полезная вещь. RSA позволяет создать два ключа: открытый и закрытый. Разместить открытый ключ где-то и им шифровать, а расшифровать сможет только обладатель закрытого ключа.
Например, мы можем сделать веб магазин на ПХП, который будет принимать заказы с данными кредитных карт. Магазин на ПХП будет шифровать данные кредитных карт открытым ключем. Сам пхп-магазин расшифровать эти зашифрованные данные уже не сможет. Хорошее решение, хакер неожиданно так взломает веб магазин (написанный на ПХП), а карты зашифрованы.
Но как же владелец сайта будет получать доступ к картам? Ему нужно взять шифротекст, закрытый ключ и расшифровать. Можно представить, что закрытый ключ будет храниться в телефоне, и телефон может вытянуть шифротекст с админки через QR код. Но в разных языках реализация криптографии немного отличается, и моя статья как раз о том, как зашифровать текст на одном языке програмирования, а расшифровать на другом языке.
В чем могут быть отличия?
— как хранятся ключи;
— как хранится шифротекст: бинарная форма или в кодировке base64;
— паддинг.
Первым делом нам нужны ключи. Я предлагаю их создать с помощью openssl
Для экономии места на экране я выбрал 512 бит, целесообразно использовать 1024 или 2048 бит. Например, SSL gitgub.com использует 2048.
Так же размер ключа определяет максимальный объем данных, которые вы можете зашифровать, но с учетом того, что мы будем использовать OPENSSL_PKCS1_PADDING (по умолчанию в ПХП), то из размера ключа следует вычесть 11 байт и при ключе 512 бит мы можем зашифровать 53 байта. Не использовать паддинг вообще опасно, если вы не знаете зачем он нужен.
Теперь у нас есть private.pem и public.pem. Эти ключи в текстовом формате, и их будет достаточно удобно использовать в примерах. Я хочу, чтобы каждая программа состояла из одного файла, так будет наглядней.
encode.php
goo.gl/Xb7ayw
Получим, что-то типа (вы будете получать новый уникальный шифротекст при каждой попытке зашифровать текст):
decode.php
goo.gl/0CWTQ9
play.golang.org/p/nsyAw5kYDt
Go Playground всегда дают одни и те же случайные числа и поэтому результат:
Шифровать я буду с помощью jsEncrypt:
cossackpyra.github.io/april14/html/encrypt.html
И получил:
cossackpyra.github.io/april14/html/decrypt.html
Java — это так много всего, и ни фига нет.
В Android есть android.util.Base64, а Java 8 java.util.Base64, а еще есть org.apache.commons.codec.binary.Base64.
Java не умеет читать сертификаты в PEM формате, какие задачи и цели ставило руководство перед создателями java.security и javax.crypto — это мрак, но явно не экономить место на диске.
В Bouncy Castle есть PEMParser. Но Bouncy Castle в онлайн редактор не подцепишь, а в Android используется непонятно какой Bouncy Castle. Поэтому есть Spongy Castle, но это уже будет другая графа в реализации криптографии в форме «Supplement No. 5 to Part 742—Encryption Registration» на пункты 6 и 7 уже не ответишь «нет, нет».
Поэтому из private.pem можно вынуть модуль, приватную и публичную экспоненты. (Это допустимо, я изначально ключи создал с помощью openssl.)
В Java это будет выглядеть так:
Вся программа на Java 8:
goo.gl/t27IWw
(Надо нажать Compile, Execute)
КО: шифровать можно не текст, а AES ключ.
Всем весны и удачи.
Например, мы можем сделать веб магазин на ПХП, который будет принимать заказы с данными кредитных карт. Магазин на ПХП будет шифровать данные кредитных карт открытым ключем. Сам пхп-магазин расшифровать эти зашифрованные данные уже не сможет. Хорошее решение, хакер неожиданно так взломает веб магазин (написанный на ПХП), а карты зашифрованы.
Но как же владелец сайта будет получать доступ к картам? Ему нужно взять шифротекст, закрытый ключ и расшифровать. Можно представить, что закрытый ключ будет храниться в телефоне, и телефон может вытянуть шифротекст с админки через QR код. Но в разных языках реализация криптографии немного отличается, и моя статья как раз о том, как зашифровать текст на одном языке програмирования, а расшифровать на другом языке.
В чем могут быть отличия?
— как хранятся ключи;
— как хранится шифротекст: бинарная форма или в кодировке base64;
— паддинг.
Первым делом нам нужны ключи. Я предлагаю их создать с помощью openssl
openssl genrsa -out private.pem 512
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
Для экономии места на экране я выбрал 512 бит, целесообразно использовать 1024 или 2048 бит. Например, SSL gitgub.com использует 2048.
Так же размер ключа определяет максимальный объем данных, которые вы можете зашифровать, но с учетом того, что мы будем использовать OPENSSL_PKCS1_PADDING (по умолчанию в ПХП), то из размера ключа следует вычесть 11 байт и при ключе 512 бит мы можем зашифровать 53 байта. Не использовать паддинг вообще опасно, если вы не знаете зачем он нужен.
Теперь у нас есть private.pem и public.pem. Эти ключи в текстовом формате, и их будет достаточно удобно использовать в примерах. Я хочу, чтобы каждая программа состояла из одного файла, так будет наглядней.
private.pem
-----BEGIN RSA PRIVATE KEY-----
MIIBPQIBAAJBALqbHeRLCyOdykC5SDLqI49ArYGYG1mqaH9/GnWjGavZM02fos4l
c2w6tCchcUBNtJvGqKwhC5JEnx3RYoSX2ucCAwEAAQJBAKn6O+tFFDt4MtBsNcDz
GDsYDjQbCubNW+yvKbn4PJ0UZoEebwmvH1ouKaUuacJcsiQkKzTHleu4krYGUGO1
mEECIQD0dUhj71vb1rN1pmTOhQOGB9GN1mygcxaIFOWW8znLRwIhAMNqlfLijUs6
rY+h1pJa/3Fh1HTSOCCCCWA0NRFnMANhAiEAwddKGqxPO6goz26s2rHQlHQYr47K
vgPkZu2jDCo7trsCIQC/PSfRsnSkEqCX18GtKPCjfSH10WSsK5YRWAY3KcyLAQIh
AL70wdUu5jMm2ex5cZGkZLRB50yE6rBiHCd5W1WdTFoe
-----END RSA PRIVATE KEY-----
public.pem
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALqbHeRLCyOdykC5SDLqI49ArYGYG1mq
aH9/GnWjGavZM02fos4lc2w6tCchcUBNtJvGqKwhC5JEnx3RYoSX2ucCAwEAAQ==
-----END PUBLIC KEY-----
Начнем с ПХП
encode.php
<?php
$pub = <<<SOMEDATA777
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALqbHeRLCyOdykC5SDLqI49ArYGYG1mq
aH9/GnWjGavZM02fos4lc2w6tCchcUBNtJvGqKwhC5JEnx3RYoSX2ucCAwEAAQ==
-----END PUBLIC KEY-----
SOMEDATA777;
$data = "PHP is my secret love.";
$pk = openssl_get_publickey($pub);
openssl_public_encrypt($data, $encrypted, $pk);
echo chunk_split(base64_encode($encrypted));
?>
goo.gl/Xb7ayw
Получим, что-то типа (вы будете получать новый уникальный шифротекст при каждой попытке зашифровать текст):
JutBa0GLHzGrlygxwWr66cizw4W4za+DbzZweNM0iloCD7xEP9LclL013lcksJL5XhjW44U+oxpq
cX1ZSLhWuA==
decode.php
<?php
$key = <<<SOMEDATA777
-----BEGIN RSA PRIVATE KEY-----
MIIBPQIBAAJBALqbHeRLCyOdykC5SDLqI49ArYGYG1mqaH9/GnWjGavZM02fos4l
c2w6tCchcUBNtJvGqKwhC5JEnx3RYoSX2ucCAwEAAQJBAKn6O+tFFDt4MtBsNcDz
GDsYDjQbCubNW+yvKbn4PJ0UZoEebwmvH1ouKaUuacJcsiQkKzTHleu4krYGUGO1
mEECIQD0dUhj71vb1rN1pmTOhQOGB9GN1mygcxaIFOWW8znLRwIhAMNqlfLijUs6
rY+h1pJa/3Fh1HTSOCCCCWA0NRFnMANhAiEAwddKGqxPO6goz26s2rHQlHQYr47K
vgPkZu2jDCo7trsCIQC/PSfRsnSkEqCX18GtKPCjfSH10WSsK5YRWAY3KcyLAQIh
AL70wdUu5jMm2ex5cZGkZLRB50yE6rBiHCd5W1WdTFoe
-----END RSA PRIVATE KEY-----
SOMEDATA777;
$data = "JutBa0GLHzGrlygxwWr66cizw4W4za+DbzZweNM0iloCD7xEP9LclL013lcksJL5XhjW44U+oxpq cX1ZSLhWuA==";
$pk = openssl_get_privatekey($key);
openssl_private_decrypt(base64_decode($data), $out, $pk);
echo $out;
?>
goo.gl/0CWTQ9
Теперь на Go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"strings"
)
func main() {
b64 := `JutBa0GLHzGrlygxwWr66cizw4W4za+DbzZweNM0iloCD7xEP9LclL013lcksJL5XhjW44U+oxpq
cX1ZSLhWuA==
`
b1, err := Base64Dec(b64)
if err != nil {
panic(err)
}
b2, err := RsaDecrypt(b1, privateKey)
fmt.Println(string(b2), err)
b1, err = RsaEncrypt([]byte("Go the best language"), publicKey)
if err != nil {
panic(err)
}
s1 := Base64Enc(b1)
fmt.Println(s1)
b1, err = Base64Dec(s1)
b2, err = RsaDecrypt(b1, privateKey)
fmt.Println(string(b2), err)
}
func Base64Enc(b1 []byte) string {
s1 := base64.StdEncoding.EncodeToString(b1)
s2 := ""
var LEN int = 76
for len(s1) > 76 {
s2 = s2 + s1[:LEN] + "\n"
s1 = s1[LEN:]
}
s2 = s2 + s1
return s2
}
func Base64Dec(s1 string) ([]byte, error) {
s1 = strings.Replace(s1, "\n", "", -1)
s1 = strings.Replace(s1, "\r", "", -1)
s1 = strings.Replace(s1, " ", "", -1)
return base64.StdEncoding.DecodeString(s1)
}
func RsaDecrypt(ciphertext []byte, key []byte) ([]byte, error) {
block, _ := pem.Decode(key)
if block == nil {
return nil, errors.New("private key error!")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}
func RsaEncrypt(origData []byte, key []byte) ([]byte, error) {
block, _ := pem.Decode(key)
if block == nil {
return nil, errors.New("public key error")
}
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
pub := pubInterface.(*rsa.PublicKey)
return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}
var publicKey = []byte(`
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALqbHeRLCyOdykC5SDLqI49ArYGYG1mq
aH9/GnWjGavZM02fos4lc2w6tCchcUBNtJvGqKwhC5JEnx3RYoSX2ucCAwEAAQ==
-----END PUBLIC KEY-----
`)
var privateKey = []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIBPQIBAAJBALqbHeRLCyOdykC5SDLqI49ArYGYG1mqaH9/GnWjGavZM02fos4l
c2w6tCchcUBNtJvGqKwhC5JEnx3RYoSX2ucCAwEAAQJBAKn6O+tFFDt4MtBsNcDz
GDsYDjQbCubNW+yvKbn4PJ0UZoEebwmvH1ouKaUuacJcsiQkKzTHleu4krYGUGO1
mEECIQD0dUhj71vb1rN1pmTOhQOGB9GN1mygcxaIFOWW8znLRwIhAMNqlfLijUs6
rY+h1pJa/3Fh1HTSOCCCCWA0NRFnMANhAiEAwddKGqxPO6goz26s2rHQlHQYr47K
vgPkZu2jDCo7trsCIQC/PSfRsnSkEqCX18GtKPCjfSH10WSsK5YRWAY3KcyLAQIh
AL70wdUu5jMm2ex5cZGkZLRB50yE6rBiHCd5W1WdTFoe
-----END RSA PRIVATE KEY-----
`)
play.golang.org/p/nsyAw5kYDt
Go Playground всегда дают одни и те же случайные числа и поэтому результат:
aOleRSXhBT1XR7Al9cxdmM/8KnM2CvQdnNqnvwtq1ivFJ1aITxJUCuTw8ZRB8mY+elhoiUmC4UjM
mwyTKmjqQw==
JavaScript шифрование
Шифровать я буду с помощью jsEncrypt:
$(function () {
$('#but').click(function(){
var pub = $('#pub').val();
var crypt = new JSEncrypt();
crypt.setPublicKey(pub);
var data = $('#data').val();
$('#out').val(crypt.encrypt(data));
});
});
cossackpyra.github.io/april14/html/encrypt.html
И получил:
C2uWXwp6OsxLKnr3cXpJIf/RcPzgjlxNXj8IX2R47binEo2dLFhJISDnOioQaM8kAl/lqSSOCLdrYP12Tc/YXQ==
$(function () {
$('#but').click(function(){
var key = $('#key').val();
var crypt = new JSEncrypt();
crypt.setPrivateKey(key);
var data = $('#data').val();
$('#out').val(crypt.decrypt(data));
});
});
cossackpyra.github.io/april14/html/decrypt.html
Android не Java
Java — это так много всего, и ни фига нет.
В Android есть android.util.Base64, а Java 8 java.util.Base64, а еще есть org.apache.commons.codec.binary.Base64.
Java не умеет читать сертификаты в PEM формате, какие задачи и цели ставило руководство перед создателями java.security и javax.crypto — это мрак, но явно не экономить место на диске.
В Bouncy Castle есть PEMParser. Но Bouncy Castle в онлайн редактор не подцепишь, а в Android используется непонятно какой Bouncy Castle. Поэтому есть Spongy Castle, но это уже будет другая графа в реализации криптографии в форме «Supplement No. 5 to Part 742—Encryption Registration» на пункты 6 и 7 уже не ответишь «нет, нет».
SNAP-R
(6) Do the products incorporate encryption components produced or furnished by non-U.S. sources or vendors? (If unsure, please explain.)
No.
(7) With respect to your company's encryption products, are any of them manufactured outside the United States? If yes, provide manufacturing locations. (Insert “not applicable”, if you are not the principal producer of encryption products.)
No.
No.
(7) With respect to your company's encryption products, are any of them manufactured outside the United States? If yes, provide manufacturing locations. (Insert “not applicable”, if you are not the principal producer of encryption products.)
No.
Поэтому из private.pem можно вынуть модуль, приватную и публичную экспоненты. (Это допустимо, я изначально ключи создал с помощью openssl.)
openssl rsa -in private.pem -text -noout
Private-Key: (512 bit)
modulus:
00:ba:9b:1d:e4:4b:0b:23:9d:ca:40:b9:48:32:ea:
23:8f:40:ad:81:98:1b:59:aa:68:7f:7f:1a:75:a3:
19:ab:d9:33:4d:9f:a2:ce:25:73:6c:3a:b4:27:21:
71:40:4d:b4:9b:c6:a8:ac:21:0b:92:44:9f:1d:d1:
62:84:97:da:e7
publicExponent: 65537 (0x10001)
privateExponent:
00:a9:fa:3b:eb:45:14:3b:78:32:d0:6c:35:c0:f3:
18:3b:18:0e:34:1b:0a:e6:cd:5b:ec:af:29:b9:f8:
3c:9d:14:66:81:1e:6f:09:af:1f:5a:2e:29:a5:2e:
69:c2:5c:b2:24:24:2b:34:c7:95:eb:b8:92:b6:06:
50:63:b5:98:41
prime1:
00:f4:75:48:63:ef:5b:db:d6:b3:75:a6:64:ce:85:
03:86:07:d1:8d:d6:6c:a0:73:16:88:14:e5:96:f3:
39:cb:47
prime2:
00:c3:6a:95:f2:e2:8d:4b:3a:ad:8f:a1:d6:92:5a:
ff:71:61:d4:74:d2:38:20:82:09:60:34:35:11:67:
30:03:61
exponent1:
00:c1:d7:4a:1a:ac:4f:3b:a8:28:cf:6e:ac:da:b1:
d0:94:74:18:af:8e:ca:be:03:e4:66:ed:a3:0c:2a:
3b:b6:bb
exponent2:
00:bf:3d:27:d1:b2:74:a4:12:a0:97:d7:c1:ad:28:
f0:a3:7d:21:f5:d1:64:ac:2b:96:11:58:06:37:29:
cc:8b:01
coefficient:
00:be:f4:c1:d5:2e:e6:33:26:d9:ec:79:71:91:a4:
64:b4:41:e7:4c:84:ea:b0:62:1c:27:79:5b:55:9d:
4c:5a:1e
В Java это будет выглядеть так:
// Private key
BigInteger modulus = new BigInteger(
"BA9B1DE44B0B239DCA40B94832EA238F40AD81981B59AA687F7F1A75A319ABD9334D9FA2CE25736C3AB4272171404DB49BC6A8AC210B92449F1DD1628497DAE7",
16);
BigInteger exp = new BigInteger(
"00a9fa3beb45143b7832d06c35c0f3183b180e341b0ae6cd5becaf29b9f83c9d1466811e6f09af1f5a2e29a52e69c25cb224242b34c795ebb892b6065063b59841",
16);
//Public Key
BigInteger modulus = new BigInteger(
"BA9B1DE44B0B239DCA40B94832EA238F40AD81981B59AA687F7F1A75A319ABD9334D9FA2CE25736C3AB4272171404DB49BC6A8AC210B92449F1DD1628497DAE7",
16);
BigInteger pubExp = new BigInteger("010001", 16);
Вся программа на Java 8:
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import java.util.Base64;
//import javax.xml.bind.DatatypeConverter;
public class HelloWorld {
public static void main(String[] args) throws Exception {
try {
byte[] b1 = decrypt("JutBa0GLHzGrlygxwWr66cizw4W4za+DbzZweNM0iloCD7xEP9LclL013lcksJL5XhjW44\nU+oxpqcX1ZSLhWuA==");
String s1 = new String(b1, "UTF-8");
System.out.println(s1);
byte[] b2 = encrypt("Java kills".getBytes("UTF-8"));
String s2 = Base64.getEncoder().encodeToString(b2);
System.out.println(s2);
byte[] b3 = decrypt(s2);
String s3 = new String(b3, "UTF-8");
System.out.println(s3);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] decrypt(String key) throws Exception {
BigInteger modulus = new BigInteger(
"BA9B1DE44B0B239DCA40B94832EA238F40AD81981B59AA687F7F1A75A319ABD9334D9FA2CE25736C3AB4272171404DB49BC6A8AC210B92449F1DD1628497DAE7",
16);
BigInteger exp = new BigInteger(
"00a9fa3beb45143b7832d06c35c0f3183b180e341b0ae6cd5becaf29b9f83c9d1466811e6f09af1f5a2e29a52e69c25cb224242b34c795ebb892b6065063b59841",
16);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(modulus, exp);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decodedStr = Base64.getDecoder().decode(
key.replace("\n", "").replace("\r", "").replace(" ", ""));
byte[] plainText = cipher.doFinal(decodedStr);
return plainText;
}
private static byte[] encrypt(byte[] b1) throws Exception {
BigInteger modulus = new BigInteger(
"BA9B1DE44B0B239DCA40B94832EA238F40AD81981B59AA687F7F1A75A319ABD9334D9FA2CE25736C3AB4272171404DB49BC6A8AC210B92449F1DD1628497DAE7",
16);
BigInteger pubExp = new BigInteger("010001", 16);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, pubExp);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// byte[] decodedStr = Base64.decode(key, Base64.DEFAULT);
byte[] plainText = cipher.doFinal(b1);
return plainText;
}
}
goo.gl/t27IWw
(Надо нажать Compile, Execute)
ik1Dvev7AffP+mOgxkbnYmpZrN9nGCKEzwCA4qsADcSKZFDYC/32B4uzUNSH8D+yCjBbrE5HUDL6vs6W5idG6Q==
Android программа
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import android.util.Base64;
import android.util.Log;
public class TestX {
public static byte[] decrypt(String key) throws Exception {
BigInteger modulus = new BigInteger(
"BA9B1DE44B0B239DCA40B94832EA238F40AD81981B59AA687F7F1A75A319ABD9334D9FA2CE25736C3AB4272171404DB49BC6A8AC210B92449F1DD1628497DAE7",
16);
BigInteger exp = new BigInteger(
"00a9fa3beb45143b7832d06c35c0f3183b180e341b0ae6cd5becaf29b9f83c9d1466811e6f09af1f5a2e29a52e69c25cb224242b34c795ebb892b6065063b59841",
16);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(modulus, exp);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decodedStr = Base64.decode(key, Base64.DEFAULT);
byte[] plainText = cipher.doFinal(decodedStr);
return plainText;
}
public static void test() {
try {
byte[] b1 = decrypt("JutBa0GLHzGrlygxwWr66cizw4W4za+DbzZweNM0iloCD7xEP9LclL013lcksJL5XhjW44U+oxpq\ncX1ZSLhWuA==");
String s1 = new String(b1, "UTF-8");
Log.i("TEST", s1);
byte[] b2 = encrypt("Java kills".getBytes("UTF-8"));
String s2 = Base64.encodeToString(b2, Base64.CRLF);
Log.i("TEST", s2);
byte[] b3 = decrypt(s2);
String s3 = new String(b3, "UTF-8");
Log.i("TEST", s3);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] encrypt(byte[] b1) throws Exception {
BigInteger modulus = new BigInteger(
"BA9B1DE44B0B239DCA40B94832EA238F40AD81981B59AA687F7F1A75A319ABD9334D9FA2CE25736C3AB4272171404DB49BC6A8AC210B92449F1DD1628497DAE7",
16);
BigInteger pubExp = new BigInteger("010001", 16);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, pubExp);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = kf.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] plainText = cipher.doFinal(b1);
return plainText;
}
}
КО: шифровать можно не текст, а AES ключ.
Всем весны и удачи.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Комментарии (13)
Disasm
15.04.2015 13:01> Сам пхп-магазин расшифровать эти зашифрованные данные уже не сможет. Хорошее решение, хакер неожиданно так взломает веб магазин (написанный на ПХП), а карты зашифрованы.
Зато сможет «расшифровать» все шифруемые данные в будущем.pyra Автор
15.04.2015 13:31ПХП это король shared хостинга, а там бывает, один пользователь может получить доступ к файлам другого пользователя, программа в cgi-bin может на некоторых хостингах прочитать исходный код ПХП файла из аккаунта другого пользователя например /home/vasyapupkin/www/conf.php
zerkms
15.04.2015 14:18+2Магазин на ПХП будет шифровать данные кредитных карт открытым ключем. Сам пхп-магазин расшифровать эти зашифрованные данные уже не сможет. Хорошее решение, хакер неожиданно так взломает веб магазин (написанный на ПХП), а карты зашифрованы.
Почитайте PCI и пообещайте, что больше не будете никогда сами хранить номера кредиток.pyra Автор
15.04.2015 14:34я не храню кредитки и не принимаю их. это вступление. статья о том как реализовать аналоги openssl_get_publickey, а вступление объясняет зачем это нужно
SamDark
Однако, как точно :)
state13
> Но Bouncy Castle в онлайн редактор не подцепишь
В этом Java виновата?
pyra Автор
Я ночью в темноте шел по квартире и ударился головой о дверь. Дверь виновата?
SamDark
Я не про это. Я вообще. В Java много библиотек доступно через Maven, но очень часто нет именно того, что нужно.
state13
Ни разу такого не было. Но, возможно, у меня просто не было таких специфических задач, как у вас.
SamDark
У меня Android. Требования по версии Java, потреблению памяти и производительности чуть разные…
pyra Автор
Вот если взять Base64, то меня смущает, что он появился аж Java 8,
за то до Java8 был
docs.oracle.com/javase/7/docs/api/javax/xml/bind/DatatypeConverter.html умеющий Base64
а андроиде есть
android.util.Base64
но почему они все городят свой?
SamDark
Потому что основная на Android долгое время была пятёрка, наверное.