/** * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.seedstack.seed.core.internal.crypto; import org.seedstack.seed.SeedException; import org.seedstack.seed.crypto.EncryptionService; import javax.annotation.Nullable; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; class EncryptionServiceImpl implements EncryptionService { private static final String CIPHER = "RSA/ECB/PKCS1PADDING"; private final String alias; private final PublicKey publicKey; private final Key privateKey; EncryptionServiceImpl(String alias, @Nullable PublicKey publicKey, @Nullable Key privateKey) { this.alias = alias; this.publicKey = publicKey; this.privateKey = privateKey; } @Override public byte[] encrypt(byte[] toCrypt) { if (this.publicKey == null) { throw SeedException.createNew(CryptoErrorCode.MISSING_PUBLIC_KEY).put("alias", alias); } return doEncryptionOrDecryption(toCrypt, publicKey, Cipher.ENCRYPT_MODE); } @Override public byte[] decrypt(byte[] toDecrypt) { if (this.privateKey == null) { throw SeedException.createNew(CryptoErrorCode.MISSING_PRIVATE_KEY).put("alias", alias); } return doEncryptionOrDecryption(toDecrypt, privateKey, Cipher.DECRYPT_MODE); } /** * Encrypts or decrypts a byte[]. * * @param crypt byte[] to encrypt or decrypt * @param key key to use * @param mode {@link Cipher#DECRYPT_MODE} to decrypt or {@link Cipher#ENCRYPT_MODE} to encrypt * @return byte[] encrypted or decrypted */ private byte[] doEncryptionOrDecryption(byte[] crypt, Key key, int mode) { Cipher rsaCipher; try { rsaCipher = Cipher.getInstance(CIPHER); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw SeedException.wrap(e, CryptoErrorCode.UNABLE_TO_GET_CIPHER) .put("alias", alias) .put("cipher", CIPHER); } try { rsaCipher.init(mode, key); } catch (InvalidKeyException e) { throw SeedException.wrap(e, CryptoErrorCode.INVALID_KEY) .put("alias", alias); } try { return rsaCipher.doFinal(crypt); } catch (IllegalBlockSizeException | BadPaddingException e) { throw SeedException.wrap(e, CryptoErrorCode.UNEXPECTED_EXCEPTION); } } }