static AlgorithmParameterSpec extractGcmSpec(ASN1Primitive spec) throws InvalidParameterSpecException { try { GCMParameters gcmParams = GCMParameters.getInstance(spec); Constructor constructor = gcmSpecClass.getConstructor(new Class[] {Integer.TYPE, byte[].class}); return (AlgorithmParameterSpec) constructor.newInstance( new Object[] {Integers.valueOf(gcmParams.getIcvLen() * 8), gcmParams.getNonce()}); } catch (NoSuchMethodException e) { throw new InvalidParameterSpecException("No constructor found!"); // should never happen } catch (Exception e) { throw new InvalidParameterSpecException( "Construction failed: " + e.getMessage()); // should never happen } }
private void testGCMParameterSpec(byte[] K, byte[] N, byte[] A, byte[] P, byte[] C) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchProviderException, IOException { Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC"); SecretKeySpec key = new SecretKeySpec(K, "AES"); // GCMParameterSpec mapped to AEADParameters and overrides default MAC // size GCMParameterSpec spec = new GCMParameterSpec(128, N); eax.init(Cipher.ENCRYPT_MODE, key, spec); eax.updateAAD(A); byte[] c = eax.doFinal(P); if (!areEqual(C, c)) { fail("JCE encrypt with additional data and GCMParameterSpec failed."); } eax.init(Cipher.DECRYPT_MODE, key, spec); eax.updateAAD(A); byte[] p = eax.doFinal(C); if (!areEqual(P, p)) { fail("JCE decrypt with additional data and GCMParameterSpec failed."); } AlgorithmParameters algParams = eax.getParameters(); byte[] encParams = algParams.getEncoded(); GCMParameters gcmParameters = GCMParameters.getInstance(encParams); if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen()) { fail("parameters mismatch"); } }