List of usage examples for org.bouncycastle.jcajce.spec UserKeyingMaterialSpec UserKeyingMaterialSpec
public UserKeyingMaterialSpec(byte[] userKeyingMaterial)
From source file:com.distrimind.util.crypto.EllipticCurveDiffieHellmanAlgorithm.java
License:Open Source License
private void setDistantPublicKey(byte[] distantPublicKeyBytes, SymmetricEncryptionType symmetricEncryptionType, SymmetricAuthentifiedSignatureType symmetricSignatureType, byte[] keyingMaterial) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException, InvalidAlgorithmParameterException { CodeProvider.encureProviderLoaded(type.getCodeProvider()); try {//from w ww. j a v a 2s .c o m valid = false; if (distantPublicKeyBytes == null) throw new NullPointerException(); if (keyingMaterial == null) throw new NullPointerException(); if (keyingMaterial.length == 0) throw new IllegalArgumentException(); if (derivedKey != null) throw new IllegalArgumentException( "A key exchange process has already been begun. Use reset fonction before calling this function."); ASymmetricPublicKey distantPublicKey = (ASymmetricPublicKey) Key.decode(distantPublicKeyBytes); if (myKeyPair.getASymmetricPublicKey().equals(distantPublicKey)) throw new InvalidKeyException("The local et distant public keys cannot be similar !"); AbstractKeyAgreement ka; if (symmetricEncryptionType == null) ka = type.getKeyAgreementInstance(symmetricSignatureType); else ka = type.getKeyAgreementInstance(symmetricEncryptionType); if (type.isECCDHType() || type.isXDHType()) { UserKeyingMaterialSpec spec = null; if (type.useKDF()) spec = new UserKeyingMaterialSpec(keyingMaterial); ka.init(myKeyPair.getASymmetricPrivateKey(), spec, randomForKeys); } else if (type.isECMQVType()) { throw new InternalError( "Next code must use ephemeral and static keys. It must be completed/corrected."); /*ka.init(myKeyPair.getASymmetricPrivateKey(), new Object[] { FipsEC.MQV.using( (AsymmetricECPublicKey)myKeyPair.getASymmetricPublicKey().toBouncyCastleKey(), (AsymmetricECPrivateKey)myKeyPair.getASymmetricPrivateKey().toBouncyCastleKey(), (AsymmetricECPublicKey)distantPublicKey.toBouncyCastleKey()), keyingMaterial, } );*/ } ka.doPhase(distantPublicKey, true); if (ka instanceof JavaNativeKeyAgreement) derivedKey = ka.generateSecretKey(keySizeBits); else derivedKey = ka.generateSecretKey((short) (keySizeBits / 8)); valid = true; } catch (NoSuchAlgorithmException e) { throw new NoSuchAlgorithmException(e); } catch (NoSuchProviderException e) { throw new NoSuchAlgorithmException(e.getMessage()); } }
From source file:com.pazdev.jose.JWE.java
License:Apache License
public byte[] decrypt(int recipientIndex, Key decryptKey) { // steps 1 - 3 occur naturally // step 4/* www . ja va2 s.c o m*/ Header ph, sh, rh; if (recipients != null && !recipients.isEmpty()) { rh = recipients.get(recipientIndex).header; } else { rh = header; } ph = getProtectedHeaderAsObject(); sh = getUnprotectedHeader(); Header joseHeader = Header.merge(ph, sh, rh); if (joseHeader.getCritical() != null && !joseHeader.getCritical().isEmpty()) { throw new UnsupportedOperationException("Cannot process critical elements"); } // step 6 Algorithm alg = joseHeader.getAlgorithm(); Algorithm enc = joseHeader.getEncryptionAlgorithm(); Algorithm zip = joseHeader.getCompressionAlgorithm(); Key kek, cek; // step 7... how did we get this far without a key? if (Algorithm.ECDH_ES.equals(alg) || Algorithm.ECDH_ES_A128KW.equals(alg) || Algorithm.ECDH_ES_A192KW.equals(alg) || Algorithm.ECDH_ES_A256KW.equals(alg)) { // step 8 JWK eph = joseHeader.getEphemeralPublicKey(); Key publicKey = eph.getKeys().get("public"); try { KeyAgreement ka = KeyAgreement.getInstance("ECCDHwithSHA256CKDF", "BC"); byte[] apu = joseHeader.getAgreementPartyUInfo(); byte[] apv = joseHeader.getAgreementPartyVInfo(); if (apu == null) { apu = new byte[0]; } if (apv == null) { apv = new byte[0]; } Algorithm keyalg = alg; if (alg == Algorithm.ECDH_ES) { keyalg = enc; } int otherInfoSize = 0; otherInfoSize += 4 + keyalg.getName().length(); otherInfoSize += 4 + apu.length; otherInfoSize += 4 + apv.length; otherInfoSize += 4; // SuppPubInfo byte[] otherInfo = new byte[otherInfoSize]; ByteBuffer buf = ByteBuffer.wrap(otherInfo); buf.putInt(keyalg.getName().length()); buf.put(keyalg.getName().getBytes(StandardCharsets.US_ASCII)); buf.putInt(apu.length); buf.put(apu); buf.putInt(apv.length); buf.put(apv); buf.putInt(keyalg.getByteSize()); UserKeyingMaterialSpec spec = new UserKeyingMaterialSpec(otherInfo); ka.init(decryptKey, spec); ka.doPhase(publicKey, true); // multiplying bit size by 8 to resolve a bug in Bouncy Castle // refer to org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi.java:179 // and org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi.java:263 SecretKey sharedKey = ka.generateSecret(String.format("AES[%d]", keyalg.getBitSize() * 8)); if (Algorithm.ECDH_ES.equals(alg)) { kek = null; cek = sharedKey; } else { kek = sharedKey; cek = null; } } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException e) { throw new RuntimeException(e); } } else if (Algorithm.RSA1_5.equals(alg) || Algorithm.RSA_OAEP.equals(alg) || Algorithm.RSA_OAEP_256.equals(alg) || Algorithm.A128KW.equals(alg) || Algorithm.A192KW.equals(alg) || Algorithm.A256KW.equals(alg) || Algorithm.A128GCMKW.equals(alg) || Algorithm.A192GCMKW.equals(alg) || Algorithm.A256GCMKW.equals(alg) || Algorithm.PBES2_HS256_A128KW.equals(alg) || Algorithm.PBES2_HS384_A192KW.equals(alg) || Algorithm.PBES2_HS512_A256KW.equals(alg)) { kek = decryptKey; cek = null; } else if (Algorithm.DIR.equals(alg)) { // step 11 kek = null; cek = decryptKey; } else { throw new UnsupportedOperationException(); } byte[] encryptedCEK; if (recipients != null) { encryptedCEK = recipients.get(recipientIndex).encryptedKey; } else { encryptedCEK = encryptedKey; } // step 9 try { if (Algorithm.RSA1_5.equals(alg)) { Cipher c = Cipher.getInstance("RSA/NONE/PKCS1Padding", "BC"); c.init(Cipher.UNWRAP_MODE, kek); cek = c.unwrap(encryptedCEK, "AES", Cipher.SECRET_KEY); } else if (Algorithm.RSA_OAEP.equals(alg)) { Cipher c = Cipher.getInstance("RSA/NONE/OAEPWithSHA1AndMGF1Padding", "BC"); c.init(Cipher.UNWRAP_MODE, kek); cek = c.unwrap(encryptedCEK, "AES", Cipher.SECRET_KEY); } else if (Algorithm.RSA_OAEP_256.equals(alg)) { Cipher c = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", "BC"); c.init(Cipher.UNWRAP_MODE, kek); cek = c.unwrap(encryptedCEK, "AES", Cipher.SECRET_KEY); } else if (Algorithm.A128KW.equals(alg) || Algorithm.A128KW.equals(alg) || Algorithm.A256KW.equals(alg) || Algorithm.ECDH_ES_A128KW.equals(alg) || Algorithm.ECDH_ES_A192KW.equals(alg) || Algorithm.ECDH_ES_A256KW.equals(alg) || Algorithm.PBES2_HS256_A128KW.equals(alg) || Algorithm.PBES2_HS384_A192KW.equals(alg) || Algorithm.PBES2_HS512_A256KW.equals(alg)) { Cipher c = Cipher.getInstance("AESWrap", "BC"); c.init(Cipher.UNWRAP_MODE, kek); cek = c.unwrap(encryptedCEK, "AES", Cipher.SECRET_KEY); } else if (Algorithm.A128GCMKW.equals(alg) || Algorithm.A192GCMKW.equals(alg) || Algorithm.A256GCMKW.equals(alg)) { byte[] cipheredKey = new byte[encryptedCEK.length + 16]; ByteBuffer buf = ByteBuffer.wrap(cipheredKey); buf.put(encryptedCEK); buf.put(joseHeader.getAuthenticationTag()); Cipher c = Cipher.getInstance("AES/GCM/NoPadding", "BC"); byte[] keyIV = joseHeader.getInitializationVector(); c.init(Cipher.UNWRAP_MODE, kek, new GCMParameterSpec(128, keyIV)); cek = c.unwrap(cipheredKey, "AES", Cipher.SECRET_KEY); } } catch (NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException | InvalidKeyException | InvalidAlgorithmParameterException e) { throw new RuntimeException(e); } // step 10 if (Algorithm.DIR.equals(alg) || Algorithm.ECDH_ES.equals(alg) && encryptedCEK != null && encryptedCEK.length > 0) { throw new IllegalArgumentException("An encrypted key exists when direct algorithms are used"); } // step 12 if (cek == null) { throw new IllegalArgumentException("The content key cannot be found"); } // step 13 is implemented by this method being called per recipient // step 14 String protectedString = Base64.getUrlEncoder().withoutPadding().encodeToString(protectedHeader); // step 15 byte[] jweAAD; if (aad != null && aad.length > 0) { String aadString = Base64.getUrlEncoder().withoutPadding().encodeToString(aad); jweAAD = String.format("%s.%s", protectedString, aadString).getBytes(StandardCharsets.US_ASCII); } else { jweAAD = protectedString.getBytes(StandardCharsets.US_ASCII); } byte[] output; // step 16 try { if (Algorithm.A128CBC_HS256.equals(enc) || Algorithm.A192CBC_HS384.equals(enc) || Algorithm.A256CBC_HS512.equals(enc)) { byte[] k = cek.getEncoded(); byte[] macKey = Arrays.copyOf(k, enc.getByteSize()); byte[] encKey = Arrays.copyOfRange(k, enc.getByteSize(), k.length); byte[] al = new byte[Long.BYTES]; ByteBuffer buf = ByteBuffer.wrap(al); buf.putLong((long) jweAAD.length); Mac mac; int tLen; if (Algorithm.A128CBC_HS256.equals(enc)) { mac = Mac.getInstance("HmacSHA256", "BC"); mac.init(new SecretKeySpec(macKey, "HmacSHA256")); tLen = 16; } else if (Algorithm.A192CBC_HS384.equals(enc)) { mac = Mac.getInstance("HmacSHA384", "BC"); mac.init(new SecretKeySpec(macKey, "HmacSHA384")); tLen = 24; } else if (Algorithm.A256CBC_HS512.equals(enc)) { mac = Mac.getInstance("HmacSHA512", "BC"); mac.init(new SecretKeySpec(macKey, "HmacSHA512")); tLen = 32; } else { throw new IllegalStateException("Unsupported HMAC"); } mac.update(jweAAD); mac.update(iv); mac.update(ciphertext); mac.update(al); byte[] thistag = mac.doFinal(); boolean match = true; for (int i = tLen - 1; i >= 0; --i) { if (tag[i] != thistag[i]) { match = false; } } if (!match) { throw new IllegalArgumentException("The message is invalid"); } Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(encKey, "AES"), new IvParameterSpec(iv)); output = c.doFinal(ciphertext); } else if (Algorithm.A128GCM.equals(enc) || Algorithm.A192GCM.equals(enc) || Algorithm.A256GCM.equals(enc)) { Cipher c = Cipher.getInstance("AES/GCM/NoPadding", "BC"); c.init(Cipher.DECRYPT_MODE, cek, new GCMParameterSpec(128, iv)); c.updateAAD(jweAAD); byte[] block = new byte[ciphertext.length + tag.length]; ByteBuffer buf = ByteBuffer.wrap(block); buf.put(ciphertext); buf.put(tag); try { output = c.doFinal(block); } catch (AEADBadTagException e) { throw new IllegalArgumentException("The message is invalid", e); } } else { throw new IllegalArgumentException("Unknown algorithm"); } } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException | NoSuchPaddingException e) { throw new RuntimeException(e); } // step 17 if (zip != null) { if (Algorithm.DEFLATE.equals(zip)) { try { InflaterInputStream in = new InflaterInputStream(new ByteArrayInputStream(output)); ByteArrayOutputStream out = new ByteArrayOutputStream(output.length * 2); int b; while ((b = in.read()) != -1) { out.write(b); } out.flush(); output = out.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } } else { throw new IllegalArgumentException("Unknown compression"); } } return output; }