2010-07-14 18 views
50

Sto lavorando su un test harness per un SAML 1.1 Assertion Consumer Service. Il test deve generare un SAMLResponse firmato e inviarlo all'ACS codificato in Base64. L'ACS deve essere in grado di verificare il messaggio firmato utilizzando il certificato pubblico X509.Come caricare RSA chiave privata da file

io sono in grado di costruire il SAMLResponse, aggiungendo le affermazioni necessarie, ecc, ma quando provo a firmare l'oggetto sono in esecuzione in problemi. Ecco un frammento del mio codice corrente:

String certPath = "mycert.pem"; 
File pubCertFile = new File(certPath); 
BufferedInputStream bis = null; 
try { 
    bis = new BufferedInputStream(new FileInputStream(pubCertFile)); 
} catch(FileNotFoundException e) { 
    throw new Exception("Could not locate certfile at '" + certPath + "'", e); 
} 
CertificateFactory certFact = null; 
Certificate cert = null; 
try { 
    certFact = CertificateFactory.getInstance("X.509"); 
    cert = certFact.generateCertificate(bis); 
} catch(CertificateException e) { 
    throw new Exception("Could not instantiate cert", e); 
} 
bis.close(); 
ArrayList<Certificate> certs = new ArrayList<Certificate>(); 
certs.add(cert); 

String keyPath = "mykey.pem"; 
File privKeyFile = new File(keyPath); 
try { 
    bis = new BufferedInputStream(new FileInputStream(privKeyFile)); 
} catch(FileNotFoundException e) { 
    throw new Exception("Could not locate keyfile at '" + keyPath + "'", e); 
} 
byte[] privKeyBytes = new byte[(int)privKeyFile.length()]; 
bis.read(privKeyBytes); 
bis.close(); 
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
KeySpec ks = new PKCS8EncodedKeySpec(privKeyBytes); 
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(ks); 

samlResponse.sign(Signature.getInstance("SHA1withRSA").toString(), privKey, certs); 

L'errore si verifica nella seconda-a-ultima linea. Vedo quanto segue nella console:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format 

Anche se non abituale o sicuro, ma per il bene di questa discussione, sto fornendo il CERT pubblica e chiave privata che sto usando. Ovviamente, ne creerò di nuovi una volta risolto il problema. :)

[email protected]:~/$ cat mykey.pem 
-----BEGIN RSA PRIVATE KEY----- 
MIICXgIBAAKBgQDnbcLSlDFaDMhalcmQgclTFobpkHQHJtxMVGRlbv7zknttAVbY 
1jzGjJ6HVupndzDxA9tbiMjQujmGlS/8g5IEbVsR9o6dmcmbvujtEZ2rHZ82tMYP 
VAt2IoS/W/q2Rr1cAZ/zTKEmh0ZZjzCZFueLfrYPm3am5JLcXgVtbKwybQIDAQAB 
AoGBAJ441oettYgBUUFNQv8/HGtn7Vjl38277cVptTH8DuZr8WJ3Fe8tmWONZBzX 
eW6/eIBuyJvuCo1ZpFa0zJfxQ/Ph6QlQwdN50GNfh9RzSS6lDdfy8BRhc27sypXS 
L6c5ljB6ql+pp3DdxFhJMOs3ZmBJdeyWe7uFrkngtnM1nxZBAkEA+1hbV1Q305wa 
u8YMF1SlNIAfgLJ7buD43SEXle0egz405PFG8f8yDmvROwDiRceILGVrRbInd7Cb 
dvJKr34WOQJBAOu2+reG44rNuiXeGX1MYg6TlWYyABm7PrTrhPZkedodOQB8p7zD 
AqtDSK7RnDCoThndPW6kdNAeB+kG4ug5XdUCQHRDU8UajNRSkj8nhjJIkj6twWS7 
qsMIR7Wp+An+7C1TWg5I2UNZg2MOVnNPnlseyAuZQjy0AvOnetJTk16IGWkCQQCL 
FUbOr8rnhgiGe4yywDVDwJVw3aPtiuyvOCEWeabkqkWOIf+fg7m5cFQcwxXUKBsd 
a8vp0yQSAQZN24Bb4i2ZAkEA8xGJFlFDY9HREWZnDey5STgbUeT1wYkyKcDsUrp1 
kR/3BliGqSIfje+mSKDIZqaP+gai/8bIABYAsDP/t6+cuA== 
-----END RSA PRIVATE KEY----- 

[email protected]:~/$ cat mycert.pem 
-----BEGIN CERTIFICATE----- 
MIID7zCCA1igAwIBAgIJAKrURaAaD6ulMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD 
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xHDAa 
BgNVBAoTE0hvc3R3YXkgQ29ycG9yYXRpb24xITAfBgNVBAsTGFJlc2VhcmNoIGFu 
ZCBEZXZlbG9wbWVudDEYMBYGA1UEAxMPd3d3Lmhvc3R3YXkuY29tMR0wGwYJKoZI 
hvcNAQkBFg5hakBob3N0d2F5LmNvbTAeFw0xMDA3MTQwMjMyMDhaFw0xMTA3MTQw 
MjMyMDhaMIGsMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV 
BAcTB0NoaWNhZ28xHDAaBgNVBAoTE0hvc3R3YXkgQ29ycG9yYXRpb24xITAfBgNV 
BAsTGFJlc2VhcmNoIGFuZCBEZXZlbG9wbWVudDEYMBYGA1UEAxMPd3d3Lmhvc3R3 
YXkuY29tMR0wGwYJKoZIhvcNAQkBFg5hakBob3N0d2F5LmNvbTCBnzANBgkqhkiG 
9w0BAQEFAAOBjQAwgYkCgYEA523C0pQxWgzIWpXJkIHJUxaG6ZB0BybcTFRkZW7+ 
85J7bQFW2NY8xoyeh1bqZ3cw8QPbW4jI0Lo5hpUv/IOSBG1bEfaOnZnJm77o7RGd 
qx2fNrTGD1QLdiKEv1v6tka9XAGf80yhJodGWY8wmRbni362D5t2puSS3F4FbWys 
Mm0CAwEAAaOCARUwggERMB0GA1UdDgQWBBQI/4Inzs6OH5IquItuKhIrhPb24zCB 
4QYDVR0jBIHZMIHWgBQI/4Inzs6OH5IquItuKhIrhPb246GBsqSBrzCBrDELMAkG 
A1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdDaGljYWdvMRww 
GgYDVQQKExNIb3N0d2F5IENvcnBvcmF0aW9uMSEwHwYDVQQLExhSZXNlYXJjaCBh 
bmQgRGV2ZWxvcG1lbnQxGDAWBgNVBAMTD3d3dy5ob3N0d2F5LmNvbTEdMBsGCSqG 
SIb3DQEJARYOYWpAaG9zdHdheS5jb22CCQCq1EWgGg+rpTAMBgNVHRMEBTADAQH/ 
MA0GCSqGSIb3DQEBBQUAA4GBAA388zZp6UNryC/6o44hj7wTBQdzFFM5cs3B668A 
ylAnnal+J8RMIeCHoMF4S7yFQtYdOiWeScgw3c7KXrhJK1X7fU3I+eb1t3Yp1cTI 
htyzw14AoiICFalmlVgTCsn3+uh6AXP02PTkR8osdEpUOlWap4uzSKYNKc7tLOFd 
4CkM 
-----END CERTIFICATE----- 

Grazie!

risposta

46

è necessario convertire la chiave privata nel formato PKCS8 usando seguente comando:

openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key_file -nocrypt > pkcs8_key 

Dopo questo il programma Java può leggerlo.

14

due cose. Per prima cosa, devi 64 decodificare da solo il file mykey.pem. In secondo luogo, il formato della chiave privata di openssl che si sta utilizzando non è standard e non è compatibile con PKCS8EncodedKeySpec. Se siete disposti a usare la libreria bouncycastle è possibile utilizzare alcune classi nelle librerie bouncycastle provider e bouncycastle PKIX per rendere il lavoro rapido di questo.

import java.io.BufferedReader; 
import java.io.FileReader; 
import java.security.KeyPair; 
import java.security.Security; 

import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.openssl.PEMKeyPair; 
import org.bouncycastle.openssl.PEMParser; 
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; 

// ... 

String keyPath = "mykey.pem"; 
BufferedReader br = new BufferedReader(new FileReader(keyPath)); 
Security.addProvider(new BouncyCastleProvider()); 
PEMParser pp = new PEMParser(br); 
PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject(); 
KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair); 
pp.close(); 
samlResponse.sign(Signature.getInstance("SHA1withRSA").toString(), kp.getPrivate(), certs); 
+4

Grazie per il suggerimento Greg. Sto bene con l'utilizzo di BC (lo sto già usando per firmare le chiavi), ma mi piacerebbe sapere come decodificare una chiave privata da DER usando il provider predefinito. È abbastanza facile da codificare, la decodifica non sembra così semplice ... Ho codificato la chiave chiamando key.getEncoded(). Facile come cadere da un tronco. A proposito, la chiave è stata creata usando keytool. Stavo pensando di poter decodificare usando una fabbrica di chiavi "RSA". Esiste un metodo generatePrivate() che restituisce la chiave privata desiderata, ma tale metodo richiede un KeySpec. RSAPrivateKeySpec accetta un modulo e un esponente privato. È il –

+0

Ancora nessuna soluzione? Ho lo stesso problema. (Questo non dovrebbe essere stato contrassegnato come la soluzione corretta se non è la soluzione, tra l'altro). – Vincent

+1

@Vincent: credo che sia stata la soluzione alla domanda originale. Potrebbe non aver risposto alla domanda aggiuntiva nel commento, ma quel commento è stato confuso alla fine. Inoltre, il commento è stato fatto 7 mesi dopo la mia risposta !. Tu dici di avere lo stesso problema. Può essere più preciso? –

Problemi correlati