2 * Copyright (c) 2016, 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.aaa.encrypt.impl;
10 import static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
13 import java.nio.charset.Charset;
14 import java.security.InvalidAlgorithmParameterException;
15 import java.security.InvalidKeyException;
16 import java.security.NoSuchAlgorithmException;
17 import java.security.spec.InvalidKeySpecException;
18 import java.security.spec.KeySpec;
19 import java.util.Base64;
21 import javax.crypto.BadPaddingException;
22 import javax.crypto.Cipher;
23 import javax.crypto.IllegalBlockSizeException;
24 import javax.crypto.NoSuchPaddingException;
25 import javax.crypto.SecretKey;
26 import javax.crypto.SecretKeyFactory;
27 import javax.crypto.spec.IvParameterSpec;
28 import javax.crypto.spec.PBEKeySpec;
29 import javax.crypto.spec.SecretKeySpec;
30 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
31 import org.opendaylight.yang.gen.v1.config.aaa.authn.encrypt.service.config.rev160915.EncryptServiceConfig;
32 import org.osgi.service.component.annotations.Activate;
33 import org.osgi.service.component.annotations.Component;
34 import org.osgi.service.component.annotations.Deactivate;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * Provides a basic encryption service implementation with configuration knobs.
41 * @author - Sharon Aicler (saichler@gmail.com)
44 @Component(factory = AAAEncryptionServiceImpl.FACTORY_NAME)
45 public final class AAAEncryptionServiceImpl implements AAAEncryptionService {
46 static final String FACTORY_NAME = "org.opendaylight.aaa.encrypt.impl.AAAEncryptionServiceImpl";
48 private static final Logger LOG = LoggerFactory.getLogger(AAAEncryptionServiceImpl.class);
49 private static final String CONFIG_PROP = ".config";
51 private final SecretKey key;
52 private final Cipher encryptCipher;
53 private final Cipher decryptCipher;
55 public AAAEncryptionServiceImpl(final EncryptServiceConfig configuration) {
56 final byte[] encryptionKeySalt = configuration.requireEncryptSalt();
57 IvParameterSpec tempIvSpec = null;
58 SecretKey tempKey = null;
60 final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(configuration.getEncryptMethod());
61 final KeySpec spec = new PBEKeySpec(configuration.requireEncryptKey().toCharArray(), encryptionKeySalt,
62 configuration.getEncryptIterationCount(), configuration.getEncryptKeyLength());
63 tempKey = new SecretKeySpec(keyFactory.generateSecret(spec).getEncoded(), configuration.getEncryptType());
64 tempIvSpec = new IvParameterSpec(encryptionKeySalt);
65 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
66 LOG.error("Failed to initialize secret key", e);
69 final var ivSpec = tempIvSpec;
72 cipher = Cipher.getInstance(configuration.getCipherTransforms());
73 cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
74 } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException
75 | InvalidKeyException e) {
76 LOG.error("Failed to create encrypt cipher.", e);
78 encryptCipher = cipher;
81 cipher = Cipher.getInstance(configuration.getCipherTransforms());
82 cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
83 } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException
84 | InvalidKeyException e) {
85 LOG.error("Failed to create decrypt cipher.", e);
87 decryptCipher = cipher;
88 LOG.info("AAAEncryptionService activated");
92 public AAAEncryptionServiceImpl(final Map<String, ?> properties) {
93 this((EncryptServiceConfig) verifyNotNull(properties.get(CONFIG_PROP)));
96 static Map<String, ?> props(final EncryptServiceConfig configuration) {
97 return Map.of(CONFIG_PROP, requireNonNull(configuration));
101 @SuppressWarnings("static-method")
103 LOG.info("AAAEncryptionService deactivated");
107 public String encrypt(final String data) {
108 // We could not instantiate the encryption key, hence no encryption or
109 // decryption will be done.
111 LOG.warn("Encryption Key is NULL, will not encrypt data.");
115 final byte[] cryptobytes;
117 synchronized (encryptCipher) {
118 cryptobytes = encryptCipher.doFinal(data.getBytes(Charset.defaultCharset()));
120 } catch (IllegalBlockSizeException | BadPaddingException e) {
121 LOG.error("Failed to encrypt data.", e);
124 return Base64.getEncoder().encodeToString(cryptobytes);
128 public byte[] encrypt(final byte[] data) {
129 // We could not instantiate the encryption key, hence no encryption or
130 // decryption will be done.
132 LOG.warn("Encryption Key is NULL, will not encrypt data.");
136 synchronized (encryptCipher) {
137 return encryptCipher.doFinal(data);
139 } catch (IllegalBlockSizeException | BadPaddingException e) {
140 LOG.error("Failed to encrypt data.", e);
146 public String decrypt(final String encryptedData) {
147 if (key == null || encryptedData == null || encryptedData.length() == 0) {
148 LOG.warn("String {} was not decrypted.", encryptedData);
149 return encryptedData;
152 final byte[] cryptobytes = Base64.getDecoder().decode(encryptedData);
153 final byte[] clearbytes;
155 clearbytes = decryptCipher.doFinal(cryptobytes);
156 } catch (IllegalBlockSizeException | BadPaddingException e) {
157 LOG.error("Failed to decrypt encoded data", e);
158 return encryptedData;
160 return new String(clearbytes, Charset.defaultCharset());
164 public byte[] decrypt(final byte[] encryptedData) {
165 if (encryptedData == null) {
166 LOG.warn("encryptedData is null.");
167 return encryptedData;
170 return decryptCipher.doFinal(encryptedData);
171 } catch (IllegalBlockSizeException | BadPaddingException e) {
172 LOG.error("Failed to decrypt encoded data", e);
174 return encryptedData;