PublicKey 처리 Java / PHP


Answers

음, 내 대답을 찾은 것 같아. 다음은 잘 작동하는 것으로 밝혀진 몇 가지 예제 코드입니다.

public class KeyTest{
static final String ALGORITHM           = "RSA";
static final int    KEYSIZE             = 1024;

static final String SIGNATURE_ALGORITHM = "SHA512withRSA";

static final String PUBLICKEY_PREFIX    = "-----BEGIN PUBLIC KEY-----";
static final String PUBLICKEY_POSTFIX   = "-----END PUBLIC KEY-----";
static final String PRIVATEKEY_PREFIX   = "-----BEGIN RSA PRIVATE KEY-----";
static final String PRIVATEKEY_POSTFIX  = "-----END RSA PRIVATE KEY-----";

public static void main(String args[]) {
    try {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEYSIZE);

        KeyPair keyPair = keyPairGenerator.genKeyPair();

        // THIS IS java.security

        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        System.out.println("Public java.security: Algorithm: " + publicKey.getAlgorithm() + "Format: " + publicKey.getFormat());
        System.out.println("Private java.security: Algorithm: " + privateKey.getAlgorithm() + "Format: " + privateKey.getFormat() + "\n");

        // THIS IS DER:

        byte[] publicKeyDER = publicKey.getEncoded();
        byte[] privateKeyDER = privateKey.getEncoded();

        System.out.println("Public DER: "+Arrays.toString(publicKeyDER));
        System.out.println("Private DER: "+Arrays.toString(privateKeyDER) + "\n");

        // THIS IS PEM:

        String publicKeyPEM = PUBLICKEY_PREFIX + "\n" + DatatypeConverter.printBase64Binary(publicKey.getEncoded()).replaceAll("(.{64})", "$1\n") + "\n" + PUBLICKEY_POSTFIX;
        String privateKeyPEM = PRIVATEKEY_PREFIX + "\n" + DatatypeConverter.printBase64Binary(privateKey.getEncoded()).replaceAll("(.{64})", "$1\n") + "\n" + PRIVATEKEY_POSTFIX;

        System.out.println("Public PEM: " + "\n"+publicKeyPEM);
        System.out.println("Private PEM: " + "\n"+privateKeyPEM + "\n");

        // Signing the teststring
        String message = "Lorem ipsum dolor sit amet";

        Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initSign(privateKey);
        sig.update(message.getBytes());

        byte[] signatureByteArray = sig.sign();

        String signature = "-----BEGIN SIGNATURE-----" + "\n"
                    + DatatypeConverter.printBase64Binary(signatureByteArray).replaceAll("(.{64})", "$1\n") + "\n"
                    + "-----END SIGNATURE-----";

        System.out.println("Message Plaintext: " + message);
        System.out.println("Signature: " + "\n" + signature + "\n");
    } catch (Exception e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}
}

이 출력은 다음과 같습니다.

Public java.security: Algorithm: RSAFormat: X.509
Private java.security: Algorithm: RSAFormat: PKCS#8

Public DER: [48, -127, -97, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -127, -115, 0, 48, -127, -119, 2, -127, -127, 0, -125, -8, 66, -86, -27, -55, 14, 50, 26, -103, -87, 102, 47, 126, -70, 57, -27, 103, -95, 10, 26, 25, -3, -18, -44, -85, 11, -19, -92, 111, 22, -6, 94, 79, -126, 32, -68, -82, -67, 24, -108, 9, 46, -100, 25, -37, 56, 2, -122, -31, -93, 56, -39, 79, -67, 33, -126, -13, -72, -120, 115, 3, -57, -120, -86, 119, 57, -110, -6, -11, -36, 109, -113, -69, -11, -81, -94, 47, 59, -7, 119, 108, -89, -26, -55, 117, -74, 125, -39, -1, 116, -116, -9, -60, -57, -78, -118, 45, 38, 120, -43, 123, -51, -104, 42, -47, 101, -120, 78, 9, -2, -84, 113, -42, -71, 101, 3, -44, -58, 39, 50, 96, 83, 90, 71, 41, 83, -13, 2, 3, 1, 0, 1]
Private DER: [48, -126, 2, 118, 2, 1, 0, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 4, -126, 2, 96, 48, -126, 2, 92, 2, 1, 0, 2, -127, -127, 0, -125, -8, 66, -86, -27, -55, 14, 50, 26, -103, -87, 102, 47, 126, -70, 57, -27, 103, -95, 10, 26, 25, -3, -18, -44, -85, 11, -19, -92, 111, 22, -6, 94, 79, -126, 32, -68, -82, -67, 24, -108, 9, 46, -100, 25, -37, 56, 2, -122, -31, -93, 56, -39, 79, -67, 33, -126, -13, -72, -120, 115, 3, -57, -120, -86, 119, 57, -110, -6, -11, -36, 109, -113, -69, -11, -81, -94, 47, 59, -7, 119, 108, -89, -26, -55, 117, -74, 125, -39, -1, 116, -116, -9, -60, -57, -78, -118, 45, 38, 120, -43, 123, -51, -104, 42, -47, 101, -120, 78, 9, -2, -84, 113, -42, -71, 101, 3, -44, -58, 39, 50, 96, 83, 90, 71, 41, 83, -13, 2, 3, 1, 0, 1, 2, -127, -128, 39, -40, 45, -16, -63, 62, 9, -18, 48, -65, -46, 56, -117, 0, 125, 35, 123, -46, -28, -7, 82, -42, 36, 40, 22, -57, -87, -21, 79, 41, 71, 75, -62, 107, -55, 3, 47, 84, -90, -67, 35, -4, -3, -72, -99, -55, -27, 72, 70, 7, 28, 43, -50, -40, -41, 102, -91, -50, 6, 26, 20, 119, -64, -89, 96, 97, -101, 103, -46, 34, 95, -91, 19, 43, 4, 63, -121, 30, 85, 11, 86, 33, 58, -62, -108, 74, 56, 81, -123, 24, -8, 121, -11, -119, 43, -97, -50, 24, -60, 72, -15, 6, -87, 123, -16, 123, -17, -39, 56, -44, 97, -57, -8, 16, 9, -72, 68, 53, 1, 87, 94, -16, -54, 115, 15, -34, 93, -23, 2, 65, 0, -59, 121, -7, -34, 118, -24, 27, -9, 83, -125, -115, 120, -78, 33, -122, -78, 7, 33, 18, -44, -57, -87, 50, 99, -105, -68, -69, -82, 116, 53, -119, 113, 41, -115, 83, 66, -55, -9, -47, -12, 49, -58, 14, 68, -76, 106, 95, 102, -96, 90, -61, -40, -17, -10, 81, 116, -6, -125, -68, -33, -18, -19, 43, -11, 2, 65, 0, -85, 20, 118, 69, 108, -51, 79, -63, 70, -35, -16, -47, 81, -48, 51, 36, 99, 79, -78, -84, -86, 41, 49, -56, 101, 100, -80, 121, 53, -5, -98, -9, 53, 110, 58, -60, -39, 39, 100, -64, -108, 36, -29, -127, -13, -110, 120, 46, -31, -79, -10, -36, -26, -94, -117, -6, -76, 121, -15, -17, -31, 94, -73, 71, 2, 64, 119, 0, 35, 48, 9, 77, -92, 20, -83, -47, -9, -67, -60, -14, 105, 29, -3, 39, -44, 22, 63, 95, 89, -117, 36, -108, 74, 49, 61, -68, 73, 95, -43, 31, 98, 14, 60, 113, 71, -89, 53, 27, 89, -37, -45, 48, -54, -34, -88, 65, 42, 6, 31, -52, -70, -105, -104, -93, 44, 125, 113, -104, -96, -59, 2, 64, 122, -26, 48, 48, -97, -128, -66, -110, -78, 62, 46, 9, -79, 36, 72, 25, 19, -34, -27, 20, 117, 9, 50, -30, 43, 52, -78, 49, -31, 61, -23, 108, -35, -51, 90, 26, -97, -123, 85, 51, -93, 56, -4, -41, 22, 11, 90, -101, 19, 55, -83, -121, -13, -121, 65, -41, -48, 94, -22, 22, -47, 104, 33, 113, 2, 65, 0, -65, 101, -127, -118, 21, 122, -114, 47, 65, -96, -37, -104, 100, 52, 38, -81, 9, -9, 120, -56, -36, -92, -52, 7, -47, -8, -101, 83, -24, -82, -81, -60, 71, -47, 111, -49, 1, 46, 16, -52, -87, -79, 21, -68, 22, 18, -37, -62, 33, 102, 40, -49, -122, -98, -83, 1, 94, 29, -85, 93, -16, -7, -57, 119]

Public PEM: 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCD+EKq5ckOMhqZqWYvfro55Weh
ChoZ/e7UqwvtpG8W+l5PgiC8rr0YlAkunBnbOAKG4aM42U+9IYLzuIhzA8eIqnc5
kvr13G2Pu/Wvoi87+Xdsp+bJdbZ92f90jPfEx7KKLSZ41XvNmCrRZYhOCf6scda5
ZQPUxicyYFNaRylT8wIDAQAB
-----END PUBLIC KEY-----
Private PEM: 
-----BEGIN RSA PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIP4QqrlyQ4yGpmp
Zi9+ujnlZ6EKGhn97tSrC+2kbxb6Xk+CILyuvRiUCS6cGds4AobhozjZT70hgvO4
iHMDx4iqdzmS+vXcbY+79a+iLzv5d2yn5sl1tn3Z/3SM98THsootJnjVe82YKtFl
iE4J/qxx1rllA9TGJzJgU1pHKVPzAgMBAAECgYAn2C3wwT4J7jC/0jiLAH0je9Lk
+VLWJCgWx6nrTylHS8JryQMvVKa9I/z9uJ3J5UhGBxwrztjXZqXOBhoUd8CnYGGb
Z9IiX6UTKwQ/hx5VC1YhOsKUSjhRhRj4efWJK5/OGMRI8Qape/B779k41GHH+BAJ
uEQ1AVde8MpzD95d6QJBAMV5+d526Bv3U4ONeLIhhrIHIRLUx6kyY5e8u650NYlx
KY1TQsn30fQxxg5EtGpfZqBaw9jv9lF0+oO83+7tK/UCQQCrFHZFbM1PwUbd8NFR
0DMkY0+yrKopMchlZLB5Nfue9zVuOsTZJ2TAlCTjgfOSeC7hsfbc5qKL+rR58e/h
XrdHAkB3ACMwCU2kFK3R973E8mkd/SfUFj9fWYsklEoxPbxJX9UfYg48cUenNRtZ
29Mwyt6oQSoGH8y6l5ijLH1xmKDFAkB65jAwn4C+krI+LgmxJEgZE97lFHUJMuIr
NLIx4T3pbN3NWhqfhVUzozj81xYLWpsTN62H84dB19Be6hbRaCFxAkEAv2WBihV6
ji9BoNuYZDQmrwn3eMjcpMwH0fibU+iur8RH0W/PAS4QzKmxFbwWEtvCIWYoz4ae
rQFeHatd8PnHdw==
-----END RSA PRIVATE KEY-----

Message Plaintext: Lorem ipsum dolor sit amet
Signature: 
-----BEGIN SIGNATURE-----
UxhWlr8Ks3PkfaKK8IGGolUs8qjvbE4dXs8ANUtJdw48g8nk6pOEuEscpSiszc1O
fBFEG6lexRFeW4+zpyWHN8oJpVaxz7sd2lstFqu/dUkU8HtPujKkwK6c/3pzsAt8
yHru/BPRwI8Wryqm2dfiHO4cXKq5rIXfj0sSXbwI1PE=
-----END SIGNATURE-----

이제 PHP에서이 값을 하드 코드했습니다.

<?php

$publicKeyPEM = "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCD+EKq5ckOMhqZqWYvfro55Weh
ChoZ/e7UqwvtpG8W+l5PgiC8rr0YlAkunBnbOAKG4aM42U+9IYLzuIhzA8eIqnc5
kvr13G2Pu/Wvoi87+Xdsp+bJdbZ92f90jPfEx7KKLSZ41XvNmCrRZYhOCf6scda5
ZQPUxicyYFNaRylT8wIDAQAB
-----END PUBLIC KEY-----";

$privateKeyPEM = "-----BEGIN RSA PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIP4QqrlyQ4yGpmp
Zi9+ujnlZ6EKGhn97tSrC+2kbxb6Xk+CILyuvRiUCS6cGds4AobhozjZT70hgvO4
iHMDx4iqdzmS+vXcbY+79a+iLzv5d2yn5sl1tn3Z/3SM98THsootJnjVe82YKtFl
iE4J/qxx1rllA9TGJzJgU1pHKVPzAgMBAAECgYAn2C3wwT4J7jC/0jiLAH0je9Lk
+VLWJCgWx6nrTylHS8JryQMvVKa9I/z9uJ3J5UhGBxwrztjXZqXOBhoUd8CnYGGb
Z9IiX6UTKwQ/hx5VC1YhOsKUSjhRhRj4efWJK5/OGMRI8Qape/B779k41GHH+BAJ
uEQ1AVde8MpzD95d6QJBAMV5+d526Bv3U4ONeLIhhrIHIRLUx6kyY5e8u650NYlx
KY1TQsn30fQxxg5EtGpfZqBaw9jv9lF0+oO83+7tK/UCQQCrFHZFbM1PwUbd8NFR
0DMkY0+yrKopMchlZLB5Nfue9zVuOsTZJ2TAlCTjgfOSeC7hsfbc5qKL+rR58e/h
XrdHAkB3ACMwCU2kFK3R973E8mkd/SfUFj9fWYsklEoxPbxJX9UfYg48cUenNRtZ
29Mwyt6oQSoGH8y6l5ijLH1xmKDFAkB65jAwn4C+krI+LgmxJEgZE97lFHUJMuIr
NLIx4T3pbN3NWhqfhVUzozj81xYLWpsTN62H84dB19Be6hbRaCFxAkEAv2WBihV6
ji9BoNuYZDQmrwn3eMjcpMwH0fibU+iur8RH0W/PAS4QzKmxFbwWEtvCIWYoz4ae
rQFeHatd8PnHdw==
-----END RSA PRIVATE KEY-----";

$message_plaintext = "Lorem ipsum dolor sit amet";

$signature = "-----BEGIN SIGNATURE-----
UxhWlr8Ks3PkfaKK8IGGolUs8qjvbE4dXs8ANUtJdw48g8nk6pOEuEscpSiszc1O
fBFEG6lexRFeW4+zpyWHN8oJpVaxz7sd2lstFqu/dUkU8HtPujKkwK6c/3pzsAt8
yHru/BPRwI8Wryqm2dfiHO4cXKq5rIXfj0sSXbwI1PE=
-----END SIGNATURE-----";

function verify_signature($message, $public_key, $signature) {
    $algorithm = OPENSSL_ALGO_SHA512;
    $hash_algorithm = 'sha512';

    $signature = str_replace('-----BEGIN SIGNATURE-----', '', $signature);
    $signature = str_replace('-----END SIGNATURE-----', '', $signature);
    $signature = base64_decode($signature);
    $success = openssl_verify($message, $signature, $public_key,    $algorithm);
    return $success;
}

var_dump(verify_signature($message_plaintext, $publicKeyPEM, $signature));

?>

... 그리고 이것은 실제로 작동합니다. 나는 아직도 잭의 해결책이 효과가없는 이유를 모르지만 오 ...

희망이 그물에 많은 크로스 플랫폼 예제를 찾지 못했기 때문에 다른 사람들이 키를 관리하는 데 도움이 ...

권이라도 권하고 싶습니다. http://pumka.net/2009/12/19/reading-writing-and-converting-rsa-keys-in-pem-der-publickeyblob-and-privatekeyblob-formats/

Question

나는 현재 RSA 키 관리 문제에 봉착하고있다. 구체적으로 말하자면, 나는 자바로 RSA 키 쌍을 만들고, 어떤 내용 (즉 String)에 서명하고 공개 키, 서명 및 서명 된 문자열을 JSON 파일 (예, JSON!)로 내보내고, 다른 서버에서 PHP를 사용하고 시그니처의 유효성을 검사합니다. 즉, JSON 데이터에서 사용 가능한 키를 다시 만들어야합니다.

게다가, 다른 방법으로 (PHP로 작성하고 Java로 확인)해야합니다.

또한 개인 키를 JSON (예, JSON 다시 :)으로 내보내고 내보내기해야합니다.

그래서 Java 쪽에서 모든 것이 원활하게 작동하는 것처럼 보입니다. 키를 만들고, JSON으로 내보내고, 다시 가져 와서 사용할 수 있습니다. 서명을 만들고 확인하는 것은 아무런 문제가되지 않습니다. 다음은 코드입니다.

키 쌍 만들기 :

public static final String  ALGORITHM           = "RSA";
public static final int     KEYSIZE             = 4096;
public static KeyPair createKeyPair() throws NoSuchAlgorithmException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
    keyPairGenerator.initialize(KEYSIZE);

    return keyPairGenerator.genKeyPair();
}

키를 String으로 내보내기 (JSON 객체로 끝남) - 비공개 키의 코드가 비슷합니다.

public static final String  PUBLICKEY_PREFIX    = "-----BEGIN PUBLIC KEY-----";
public static final String  PUBLICKEY_POSTFIX   = "-----END PUBLIC KEY-----";
public static String exportPublicKey(Key key) {
    return PUBLICKEY_PREFIX + DatatypeConverter.printBase64Binary(key.getEncoded()) + PUBLICKEY_POSTFIX;
}

위의 결과는 예를 들어

"-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtBPxEtEWws2pPN5HCB795+nQyX23ZTKJt5PoMQQpwjOY/7U5ODkwHpuHWUhAuB1qTKTUdEWbe5x7WkD6/ksSib64Xq3jIeLQrfhj+g3bGsQjtca5LyIZ/J+G55l7k/Ny/lfQQNfquCcILHW7DrnzTb0D56IOBsR/r0Vv8ZvUxnaXUQtif8Q6dme8uoqzfnF46McqThnvPDxdHmhumb7tqPffzt35bRxFBvMcAWqW0FcPAeXD6cmsOBAATh/gVe1g5J89FyK8PhkNjW3uLMmknCTQg9KoWh4+DDRrLXxqSCBbaIRMCtbhShZOIbtjurJ+ZjhR/WSPnzJrl84rTjWG3Po6jsdtJ0pRHP4YnXXXJWhMt2oTOtHTQj4+99UX7Yuyp2tmFaEdQXvm3k/qbT9PBlwEovC2yqbFMcrM7sAW09NiSDdm1ipzV+vsOGuRXF2vtNX6pplifp5va5hQY/UqmlHSygvecImP5ennFOP7G62W/Q0w0qRzOXmFHN6Hsi8D1ZlWwgjyNahoX2yvgBMzy7MMYJcqiS9GOOETaenXTZViiipceGk96crjh6LG7RudMb+WN2yRXnjdWYd0GYPsaXz/faMohfXRXzRq/oIGZ4EdHhp9TknL2rCZmfR3N4Ozi1BkszAmmQeeNrUgxEjB8TdSer4p4DfR22NFcs9M3YkCAwEAAQ==-----END PUBLIC KEY-----"

그런 다음 JSON에서 키를 다시 읽습니다.

public static PublicKey importPublicKey(String key) throws InvalidKeySpecException, NoSuchAlgorithmException  {
    key = stripKey(key);
    byte[] keyBytes = DatatypeConverter.parseBase64Binary(key);
    return KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(keyBytes));
}

public static PrivateKey importPrivateKey(String key) throws InvalidKeySpecException, NoSuchAlgorithmException  {
    key = stripKey(key);
    byte[] keyBytes = DatatypeConverter.parseBase64Binary(key);
    return KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
}

이것은 나를 위해 잘 작동합니다. 공개 키와 비공개 키를 만들고, 저장하고, 다시 가져와 사용할 수 있습니다. 를 사용하여 생성 한 서명

public static String createSignature(PrivateKey privateKey, String message) {
    String algorithm = "SHA512withRSA";
    Signature signature = null;
    String signedString = null;

    try {
        signature = Signature.getInstance(algorithm);
        signature.initSign(privateKey);
        signature.update(message.getBytes());

        byte[] signatureByteArray = signature.sign();

        signedString = "-----BEGIN SIGNATURE-----"
                + DatatypeConverter.printBase64Binary(signatureByteArray)
                + "-----END SIGNATURE-----";
    } catch(Exception e) {
        e.printStackTrace();
    }
    return signedString;    
}

java.security.Signature.verify() 사용하여 쉽게 확인할 수 있습니다. 지금까지 나는 행복하다.

이제 까다로운 부분 : 내가 만든 JSON을 다른 서버로 보내면 여기서 문제가 시작됩니다.

먼저, 헤더와 트레일러를 문자열 ( "----- BEGIN"등등 ...)에서 제거한 다음 base64_decode() 및 ASSUME을 사용하여 그 결과를 다음과 같은 키로 사용할 수 있습니다. openssl_pkey_get_private() 호출

어쨌든, 나는 아래와 같은 오류를 얻는다.

openssl_sign(): supplied key param cannot be coerced into a private key

내 열쇠를 사용할 때마다.

그래서 Java에서는 new X509EncodedKeySpec(keyBytes) 을 만들지 만 PHP에서는 이와 같은 기능 (?)이 없습니다.

내 인코딩 / 디코딩은 어디서 잘못됩니까? 사실 조금 잃어 버렸습니다. (