@Test public void testNonNullContextInfo() throws Exception { KeyPair uaKeyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE); ECPublicKey uaPublicKey = (ECPublicKey) uaKeyPair.getPublic(); byte[] authSecret = Random.randBytes(16); HybridEncrypt hybridEncrypt = new WebPushHybridEncrypt.Builder() .withAuthSecret(authSecret) .withRecipientPublicKey(uaPublicKey) .build(); byte[] plaintext = Random.randBytes(20); byte[] contextInfo = new byte[0]; try { byte[] unusedCiphertext = hybridEncrypt.encrypt(plaintext, contextInfo); fail("Expected GeneralSecurityException"); } catch (GeneralSecurityException ex) { } }
@Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo ) throws GeneralSecurityException { if (contextInfo != null) { throw new GeneralSecurityException("contextInfo must be null because it is unused"); } if (plaintext.length > recordSize - WebPushConstants.CIPHERTEXT_OVERHEAD) { throw new GeneralSecurityException("plaintext too long"); } KeyPair keyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE); ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) keyPair.getPrivate(); ECPublicKey ephemeralPublicKey = (ECPublicKey) keyPair.getPublic(); byte[] ecdhSecret = EllipticCurves.computeSharedSecret(ephemeralPrivateKey, recipientPublicPoint); byte[] ephemeralPublicKeyBytes = EllipticCurves.pointEncode( WebPushConstants.NIST_P256_CURVE_TYPE, WebPushConstants.UNCOMPRESSED_POINT_FORMAT, ephemeralPublicKey.getW()); byte[] ikm = WebPushUtil.computeIkm(ecdhSecret, authSecret, recipientPublicKey, ephemeralPublicKeyBytes); byte[] salt = Random.randBytes(WebPushConstants.SALT_SIZE); byte[] cek = WebPushUtil.computeCek(ikm, salt); byte[] nonce = WebPushUtil.computeNonce(ikm, salt); return ByteBuffer.allocate(WebPushConstants.CIPHERTEXT_OVERHEAD + plaintext.length) .put(salt) .putInt(recordSize) .put((byte) WebPushConstants.PUBLIC_KEY_SIZE) .put(ephemeralPublicKeyBytes) .put(encrypt(cek, nonce, plaintext)) .array(); }
WebPushHybridEncrypt implements HybridEncrypt { @Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo ) throws GeneralSecurityException { if (contextInfo != null) { throw new GeneralSecurityException("contextInfo must be null because it is unused"); } if (plaintext.length > recordSize - WebPushConstants.CIPHERTEXT_OVERHEAD) { throw new GeneralSecurityException("plaintext too long"); } KeyPair keyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE); ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) keyPair.getPrivate(); ECPublicKey ephemeralPublicKey = (ECPublicKey) keyPair.getPublic(); byte[] ecdhSecret = EllipticCurves.computeSharedSecret(ephemeralPrivateKey, recipientPublicPoint); byte[] ephemeralPublicKeyBytes = EllipticCurves.pointEncode( WebPushConstants.NIST_P256_CURVE_TYPE, WebPushConstants.UNCOMPRESSED_POINT_FORMAT, ephemeralPublicKey.getW()); byte[] ikm = WebPushUtil.computeIkm(ecdhSecret, authSecret, recipientPublicKey, ephemeralPublicKeyBytes); byte[] salt = Random.randBytes(WebPushConstants.SALT_SIZE); byte[] cek = WebPushUtil.computeCek(ikm, salt); byte[] nonce = WebPushUtil.computeNonce(ikm, salt); return ByteBuffer.allocate(WebPushConstants.CIPHERTEXT_OVERHEAD + plaintext.length) .put(salt) .putInt(recordSize) .put((byte) WebPushConstants.PUBLIC_KEY_SIZE) .put(ephemeralPublicKeyBytes) .put(encrypt(cek, nonce, plaintext)) .array(); } }
WebPushHybridEncrypt implements HybridEncrypt { @Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo ) throws GeneralSecurityException { if (contextInfo != null) { throw new GeneralSecurityException("contextInfo must be null because it is unused"); } if (plaintext.length > recordSize - WebPushConstants.CIPHERTEXT_OVERHEAD) { throw new GeneralSecurityException("plaintext too long"); } KeyPair keyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE); ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) keyPair.getPrivate(); ECPublicKey ephemeralPublicKey = (ECPublicKey) keyPair.getPublic(); byte[] ecdhSecret = EllipticCurves.computeSharedSecret(ephemeralPrivateKey, recipientPublicPoint); byte[] ephemeralPublicKeyBytes = EllipticCurves.pointEncode( WebPushConstants.NIST_P256_CURVE_TYPE, WebPushConstants.UNCOMPRESSED_POINT_FORMAT, ephemeralPublicKey.getW()); byte[] ikm = WebPushUtil.computeIkm(ecdhSecret, authSecret, recipientPublicKey, ephemeralPublicKeyBytes); byte[] salt = Random.randBytes(WebPushConstants.SALT_SIZE); byte[] cek = WebPushUtil.computeCek(ikm, salt); byte[] nonce = WebPushUtil.computeNonce(ikm, salt); return ByteBuffer.allocate(WebPushConstants.CIPHERTEXT_OVERHEAD + plaintext.length) .put(salt) .putInt(recordSize) .put((byte) WebPushConstants.PUBLIC_KEY_SIZE) .put(ephemeralPublicKeyBytes) .put(encrypt(cek, nonce, plaintext)) .array(); } private  WebPushHybridEncrypt(Builder builder); }
WebPushHybridEncrypt implements HybridEncrypt { @Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo ) throws GeneralSecurityException { if (contextInfo != null) { throw new GeneralSecurityException("contextInfo must be null because it is unused"); } if (plaintext.length > recordSize - WebPushConstants.CIPHERTEXT_OVERHEAD) { throw new GeneralSecurityException("plaintext too long"); } KeyPair keyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE); ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) keyPair.getPrivate(); ECPublicKey ephemeralPublicKey = (ECPublicKey) keyPair.getPublic(); byte[] ecdhSecret = EllipticCurves.computeSharedSecret(ephemeralPrivateKey, recipientPublicPoint); byte[] ephemeralPublicKeyBytes = EllipticCurves.pointEncode( WebPushConstants.NIST_P256_CURVE_TYPE, WebPushConstants.UNCOMPRESSED_POINT_FORMAT, ephemeralPublicKey.getW()); byte[] ikm = WebPushUtil.computeIkm(ecdhSecret, authSecret, recipientPublicKey, ephemeralPublicKeyBytes); byte[] salt = Random.randBytes(WebPushConstants.SALT_SIZE); byte[] cek = WebPushUtil.computeCek(ikm, salt); byte[] nonce = WebPushUtil.computeNonce(ikm, salt); return ByteBuffer.allocate(WebPushConstants.CIPHERTEXT_OVERHEAD + plaintext.length) .put(salt) .putInt(recordSize) .put((byte) WebPushConstants.PUBLIC_KEY_SIZE) .put(ephemeralPublicKeyBytes) .put(encrypt(cek, nonce, plaintext)) .array(); } private  WebPushHybridEncrypt(Builder builder); @Override byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */); }
WebPushHybridEncrypt implements HybridEncrypt { @Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo ) throws GeneralSecurityException { if (contextInfo != null) { throw new GeneralSecurityException("contextInfo must be null because it is unused"); } if (plaintext.length > recordSize - WebPushConstants.CIPHERTEXT_OVERHEAD) { throw new GeneralSecurityException("plaintext too long"); } KeyPair keyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE); ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) keyPair.getPrivate(); ECPublicKey ephemeralPublicKey = (ECPublicKey) keyPair.getPublic(); byte[] ecdhSecret = EllipticCurves.computeSharedSecret(ephemeralPrivateKey, recipientPublicPoint); byte[] ephemeralPublicKeyBytes = EllipticCurves.pointEncode( WebPushConstants.NIST_P256_CURVE_TYPE, WebPushConstants.UNCOMPRESSED_POINT_FORMAT, ephemeralPublicKey.getW()); byte[] ikm = WebPushUtil.computeIkm(ecdhSecret, authSecret, recipientPublicKey, ephemeralPublicKeyBytes); byte[] salt = Random.randBytes(WebPushConstants.SALT_SIZE); byte[] cek = WebPushUtil.computeCek(ikm, salt); byte[] nonce = WebPushUtil.computeNonce(ikm, salt); return ByteBuffer.allocate(WebPushConstants.CIPHERTEXT_OVERHEAD + plaintext.length) .put(salt) .putInt(recordSize) .put((byte) WebPushConstants.PUBLIC_KEY_SIZE) .put(ephemeralPublicKeyBytes) .put(encrypt(cek, nonce, plaintext)) .array(); } private  WebPushHybridEncrypt(Builder builder); @Override byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */);  }