695c204f40a0703e96ed3027c4c36582a7f71a31
[aaa.git] / aaa-encrypt-service / impl / src / main / java / org / opendaylight / aaa / encrypt / impl / AAAEncryptionServiceImpl.java
1 /*
2  * Copyright (c) 2016, 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.aaa.encrypt.impl;
9
10 import static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
12
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;
20 import java.util.Map;
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;
37
38 /**
39  * Provides a basic encryption service implementation with configuration knobs.
40  *
41  * @author - Sharon Aicler (saichler@gmail.com)
42  */
43 @Deprecated
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";
47
48     private static final Logger LOG = LoggerFactory.getLogger(AAAEncryptionServiceImpl.class);
49     private static final String CONFIG_PROP = ".config";
50
51     private final SecretKey key;
52     private final Cipher encryptCipher;
53     private final Cipher decryptCipher;
54
55     public AAAEncryptionServiceImpl(final EncryptServiceConfig configuration) {
56         final byte[] encryptionKeySalt = configuration.requireEncryptSalt();
57         IvParameterSpec tempIvSpec = null;
58         SecretKey tempKey = null;
59         try {
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);
67         }
68         key = tempKey;
69         final var ivSpec = tempIvSpec;
70         Cipher cipher = null;
71         try {
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);
77         }
78         encryptCipher = cipher;
79         cipher = null;
80         try {
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);
86         }
87         decryptCipher = cipher;
88         LOG.info("AAAEncryptionService activated");
89     }
90
91     @Activate
92     public AAAEncryptionServiceImpl(final Map<String, ?> properties) {
93         this((EncryptServiceConfig) verifyNotNull(properties.get(CONFIG_PROP)));
94     }
95
96     static Map<String, ?> props(final EncryptServiceConfig configuration) {
97         return Map.of(CONFIG_PROP, requireNonNull(configuration));
98     }
99
100     @Deactivate
101     @SuppressWarnings("static-method")
102     void deactivate() {
103         LOG.info("AAAEncryptionService deactivated");
104     }
105
106     @Override
107     public String encrypt(final String data) {
108         // We could not instantiate the encryption key, hence no encryption or
109         // decryption will be done.
110         if (key == null) {
111             LOG.warn("Encryption Key is NULL, will not encrypt data.");
112             return data;
113         }
114
115         final byte[] cryptobytes;
116         try {
117             synchronized (encryptCipher) {
118                 cryptobytes = encryptCipher.doFinal(data.getBytes(Charset.defaultCharset()));
119             }
120         } catch (IllegalBlockSizeException | BadPaddingException e) {
121             LOG.error("Failed to encrypt data.", e);
122             return data;
123         }
124         return Base64.getEncoder().encodeToString(cryptobytes);
125     }
126
127     @Override
128     public byte[] encrypt(final byte[] data) {
129         // We could not instantiate the encryption key, hence no encryption or
130         // decryption will be done.
131         if (key == null) {
132             LOG.warn("Encryption Key is NULL, will not encrypt data.");
133             return data;
134         }
135         try {
136             synchronized (encryptCipher) {
137                 return encryptCipher.doFinal(data);
138             }
139         } catch (IllegalBlockSizeException | BadPaddingException e) {
140             LOG.error("Failed to encrypt data.", e);
141             return data;
142         }
143     }
144
145     @Override
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;
150         }
151
152         final byte[] cryptobytes = Base64.getDecoder().decode(encryptedData);
153         final byte[] clearbytes;
154         try {
155             clearbytes = decryptCipher.doFinal(cryptobytes);
156         } catch (IllegalBlockSizeException | BadPaddingException e) {
157             LOG.error("Failed to decrypt encoded data", e);
158             return encryptedData;
159         }
160         return new String(clearbytes, Charset.defaultCharset());
161     }
162
163     @Override
164     public byte[] decrypt(final byte[] encryptedData) {
165         if (encryptedData == null) {
166             LOG.warn("encryptedData is null.");
167             return encryptedData;
168         }
169         try {
170             return decryptCipher.doFinal(encryptedData);
171         } catch (IllegalBlockSizeException | BadPaddingException e) {
172             LOG.error("Failed to decrypt encoded data", e);
173         }
174         return encryptedData;
175     }
176 }