2014-10-02 6 views
5

Sto sviluppando un'applicazione che deve convalidare le firme SHA256withECDSA con l'aiuto delle chiavi pubbliche secp256r1 (NIST P-256, P-256, prime256v1).Come posso ottenere un oggetto PublicKey dai byte della chiave pubblica CE?

Le chiavi pubbliche vengono generate da un'applicazione diversa in un momento precedente e memorizzate nel mio database in codifica esadecimale. Il formato della stringa esadecimale qui è equivalente alla stringa esadecimale che OpenSSL genererebbe quando chiama openssl ec -in x.pem -noout -text su un file x.pem che è stato precedentemente generato da openssl ecparam -genkey -name secp256r1 -out x.pem. Il messaggio e la firma sono ricevuti da un'altra applicazione. Si consideri il seguente dati di test:

// Stored in Database 
byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a"); 

// Received from Other Application 
byte[] message = DatatypeConverter.parseHexBinary("54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29"); 
byte[] signature = DatatypeConverter.parseHexBinary("304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654"); 

Ora questo dovrebbe essere una firma valida.

Il mio obiettivo è convalidare la firma sul messaggio utilizzando l'API di crittografia Java e/o Bouncycastle. Ho creato un metodo isValidSignature per questo:

private static boolean isValidSignature(byte[] pubKey, byte[] message, 
     byte[] signature) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, InvalidKeySpecException { 
    Signature ecdsaVerify = Signature.getInstance("SHA256withECDSA", new BouncyCastleProvider()); 
    ecdsaVerify.initVerify(getPublicKeyFromHex(pubKey)); 
    ecdsaVerify.update(message); 
    return ecdsaVerify.verify(signature); 
} 

ho cercato di estrarre la chiave pubblica:

KeyFactory.generatePublic:

private static PublicKey getPublicKeyFromHex(byte[] pubKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { 
    KeyFactory fact = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider()); 
    return fact.generatePublic(new X509EncodedKeySpec(pubKey)); 
} 

Ma questo getta una lunghezza java.security.spec.InvalidKeySpecException (DER più di 4 byte: 26). Cosa posso fare per analizzare questo?

+0

Giusto per consentire la correttezza durante la copia del codice; L'opzione '-noout' per OpenSSL è errata. – CarlosRos

+0

Grazie, corretto. –

risposta

11

Il Bouncy Castle example code on elliptic curve key pair Generation and key factories mi ha fatto molto vicino.

Una volta che sono riuscito a creare una fabbrica chiave ECDSA e una specifica curva per curva secp256r1/NIST P-256/P-256/prime256v1 ero in grado di utilizzare ECPointUtil.decodePoint per ottenere un punto curva. Potrei quindi generare una specifica di chiave pubblica che mi ha permesso di generare una chiave pubblica come questa:

private PublicKey getPublicKeyFromBytes(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException { 
    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1"); 
    KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider()); 
    ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN()); 
    ECPoint point = ECPointUtil.decodePoint(params.getCurve(), pubKey); 
    ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params); 
    ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec); 
    return pk; 
} 
+0

grazie, sto provando a fare lo stesso usando solo un castello gonfiabile portatile, qualche idea? Ho fallito perché non c'è ECPointUtil in android.mono – Ivan

Problemi correlati