AWS KMS
Key Management System - один з веб сервісів Amazon покликаний для захисту інформації, а саме енкриптання (шифрування) та декриптання (розшифрування) даних за допомогою ID ключа, що зберігається на AWS.
Використання KMS є дуже рентабельним в тому плані коли вам не хочеться ламати голову над тим як шифрувати дані, як зберігати метадані шифрування (ключі, паролі чи фрази) і як захистити свій алгоритм від декомпіляції або іншого роду взломів. KMS все це інкапсулює в собі, все чим ви оперуєте це внутрішня ID ключа котрий зберігається в KMS і AWS креденшили (AccessKey ID & SecretKey) а останні означають що комусь доведеться в прямому сенсі слова "взламати" Amazon щоб добратися до ваших даних. Іншими словами використовуючи KMS ви перекладаєте обов'язок шифрування та розшифрування даних на Amazon.
Постановка задачі
В цій статті ми повинні:
- Розібратися з AwsKms клієнтом, що входить до пакету AWS SDK;
- Заміряти його перформенс і створити най оптимальнішу конфігурацію для шифрування і дешифрування 1000 об'єктів типу String, скажемо 1000 паролів користувачів, за один підхід;
- Розібратися з проблемами збереження шифрованих даних в String форматі.
Паралельно / Послідовно
AWS SDK містить дві реалізації KMS клієнта , послідовну (AWSKMSClient) і паралельну (AWSKMSAsyncClient), відрізняються вони конструкторами, паралельна версія підтримує конструктор для отримання ExecutorService (якщо його не передавати то по замовчуванню його розмір буде 50 потоків) а також паралельна версія клієнта має методи з приставкою Async, наприклад : "decryptAsync" для роботи у розпаралеленому режимі. Інші ж методи у них ідентичні (тобто обидва мають методи для роботи у послідовному режимі).
В цій статті буде використовуватись клієнт з підтримкою паралельних операцій.
Підготовка проекту
Для того щоб почати працювати з KMS треба підключити AWS SDK до проекту , я використовую наступно залежність у моєму Apache Maven проекті :
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.10.51</version>
</dependency>
Створення клієнта
Перш ніж створити клієнт і почати роботу потрібно ініціалізувати AWS креденшили, які клієнт приймає в конструкторі. Існує кілька способів отримати ці креденшили, можна імплементувати провайдер, і вже в середині вирішувати звідки отримати дані або ж просто ініціалізувати їх в коді, що ми і зробимо :
AWSCredentials awsCredentials = new AWSCredentials() {
public String getAWSAccessKeyId() {
return AWS_ACCESS_KEY_ID;
}
public String getAWSSecretKey() {
return AWS_SECRET_KEY;
}
};
Далі потрібно створити конфігурацію для нашого клієнта, звісно можна обійтися без неї (в середині і так використається конфігурація по замовчуванню). Нам вона потрібена лише щоб переконфігурувати політику ретраїв (повторних спроб), оскільки KMS має певні рестрікшени (100 реквестів в секунду на запити encrypt/decrypt та ін. одночасно) а ми використовуємо асинхронний клієнт, тому нам потрібно обробляти випадки коли виходимо за цей ліміт а також інші випадки при яких в асинхронному режимі варто повторити операцію (спершу я обробляв всі еррори і робив операції повторно в хендлері реквеста без цієї конфігурації, проте це не вірно, є випадки, наприклад: "дешифрування не валідних даних", які повторювати не треба). Сам клієнт вже має можливість повторювати певного роду помилки при роботі але по замовчуванню це вимкнено.
Отже створюємо конфігурацію і задаємо кількість повторів (далі ми будемо визначати оптимальну кількість потоків в екзекютері нашого клієнта , адже чим більше потоків і даних тим більше треба буде повторів і тим гірший буде перформенс) :
ClientConfiguration clientConfiguration = PredefinedClientConfigurations.defaultConfig();
clientConfiguration.setMaxErrorRetry(1);
Наразі встановимо кількість повторів рівною 1.
Маючи все що описано вище можна ініціалізувати KMS клієнт :
AWSKMSAsyncClient awsKmsClient = new AWSKMSAsyncClient(awsCredentials, clientConfiguration,
Executors.newFixedThreadPool(50));
В створеному клієнті ми використали наші AWS креденшили та конфігурацію, а також передали ExecutorService. Розмір пулу 50 є розміром по замовчуванню.
Шлях до AWS
Amazon має багато дата-центрів по всій планеті і всі вони мають різні зони доступу (availability zone) тому і шлях потібно вказувати додатковим параметром :
awsKmsClient.setEndpoint(AWS_ENDPOINT);
Для прикладу, шаблон шляху є таким : "https://kms.<availability_zone>.amazonaws.com", де <availability_zone> може бути: "eu-central-1".
Створення ключа для шифрування
Для шифрування даних нам потрібно використовувати Encryption Key Id (Id ключа шифрування). Щоб створити цей ключ і дізнатися його ID можна скористатися нашим KMS клієнтом або через Веб консоль AWS. Я користувався AWS веб консоллю і для того, щоб це зробити потрібно піти по наступному шляху :
Маючи все попереднє можна сміло приступати до шифрування / розшифрування даних.
Шифруємо (Data Encryption)
Для шифрування даних потрібно створити EnryptRequest і передати його на виконання нашому AWSKMSAsyncClient'у :
EncryptRequest encryptRequest = new EncryptRequest();
encryptRequest.setKeyId(KMS_KEY_ID);
encryptRequest.setPlaintext(ByteBuffer.wrap("This is text message".getBytes()));
В методі "setKeyId" використовуємо ID ключа а в метод "setPlaintext" передаємо байт-буфер даних котрі шифруються, в мому випадку це проста текстова стрічка. Також АРІ об'єкта EncryptRequest дозволяє створити його за допомогою білдера :
EncryptRequest encryptRequest = new EncryptRequest().withKeyId(KMS_KEY_ID).withPlaintext(ByteBuffer.wrap("This is text message".getBytes()));
Після цього передаємо запит шифрування на виконання нашому клієнту :
byte[] encryptedData = null;
awsKmsClient.encryptAsync(encryptRequest,
new AsyncHandler<EncryptRequest, EncryptResult>() {
public void onError(Exception e) {
//error
}
public void onSuccess(EncryptRequest request, EncryptResult encryptResult) {
// get encrypted data bytes from ByteBuffer
encryptedData = encryptResult.getCiphertextBlob().array();
}
});
Оскільки я використовую клієнт з паралельною обробкою мені потрібно обробити результат виконання обробником або ж зберегти отриманий після виконання методу "encryptAsync" об'єкт Future<EncryptResult> і дочекавшись його значення отримати бажаний результат. Як показано вище, я використав обробник і в методі "onSuccess" вичитую ByteBuffer а вже з нього беру байти закодованого повідомлення. Метод "onFailure" я тут не чіпаю, хоча з даним підходом (коли ми використали Retry Policy клієнта) можна сказати що якщо цей метод викличеться то можна сміло фейлити операцію і логувати екзепшен (раніше я пробував тут повторно виконувати шифрування, та це не є правильним адже спрацювати він може через те, наприклад, що ключа яким шифруєте нема).
Розшифровуємо (Data Decryption)
Для того щоб розшифрувати наше повідомлення також потрібно створити запит :
DecryptRequest decryptRequest = new DecryptRequest().withCiphertextBlob(ByteBuffer.wrap(encryptedData));
Як бачите, для розшифрування повідомлення не потрібно вказувати ID ключа. А все тому, що зашифровані дані містять в собі мета-дані за допомогою яких відбувається розшифрування.
Запускаємо цей запит на виконання:
String result = null;
awsKmsClient.decryptAsync(decryptRequest,
new AsyncHandler<DecryptRequest, DecryptResult>() {
public void onError(Exception e) {
//error
}
public void onSuccess(DecryptRequest request, DecryptResult decryptResult) {
byte[] data = decryptResult.getPlaintext().array();
result = new String(data);
}
});
Аналогічно шифруванню, тут я використовує обробник. Як тільки виконається метод "onSuccess" я дістаю байти повідомлення і перетворюю в стрінгу.
Усе вище працює без проблем. Загалом схему шифрування та дешифрування можна зобрадити так :
Проблеми зі збереженням шифрованих даних у форматі String
Моя задача передбачала що дані (шифровані чи ні) передаються і зберігаються у форматі String. А String має конструктор що приймає масив байтів, тому паємо щойно зашифровані дані в стрінгу і зберігаємо (чи передаємо). Проте як тільки ми спробуємо перетворити стрінгу назад в байти і розшифрувати, ми отримаємо екзепшен з повідомленням :
Service: AWSKMS; Status Code: 400; Error Code: InvalidCiphertextException; Request ID: <your_request_id>
Для цього було використано утиліту з пакету Apache Commons.
Отриманий після цього масив байтів можна спокійно приводити до об'єкту String і зберігати, надсилати чи що кому треба. Насправді навіть порівнюючи (при виводі) стрінгу створену з масиву байт шифрованих KMS'ом і стрінгу створену з тих же даних тільки перетворених у Base64 було чітко видно що стрінга першого варіанту взагалі була не "валідною" - містила пусті символи (підозрюю просто не відображалися) та якісь ієрогліфи, а друга стрінга була просто хаотичним набором латинських літер та символів, що зарактерно для відображення будь-якої захифрованої інформації.
Звісно треба не забути що в такому випадку для розшиврування даних потрібно їх привезти з Base64 у нормальний вигляд :
byte[] decoded = Base64.decodeBase64(data);
І вже цей набір байтів розшифровувати за допомогою KMS.
Звісно це лише мій випадок, коли я зберагаю у форматі String, якщо у вас є можливість зберігати це як маисв байтів або blob об'єкт то цього не потрібно.
Тестування в одному потоці та пошук оптимальних значень повторів та розміру пула потоків для клієнта
Для визначення найоптимальніших налаштуванн KMS клієнта поставимо наступні умови :
- Зашифрувати 1000 повідомлень;
- Розшифрувати 1000 повідомлень.
Отже запускаємо наш тестовий стенд (посилання на вихідний код буде в кінці) з розміром пула потоків 50 та кількісттю повторних спроб 2 :
- 978 повідомлень успішно зашифровані;
- 22 повідомлення не було зашифровано успішно;
- Аплікація не дойшла до розшифрування так як не всі повідомлення зашифрувалися;
- Ось таке повідомлення в консолі :
You have exceeded the rate at which you may call KMS. Reduce the frequency of your calls. (Service: AWSKMS; Status Code: 400; Error Code: ThrottlingException; Request ID: <your_request_id>
Що сталося?
AWS KMS має ліміти на з'єднання, для encrypt i decrypt операції це 100 запитів в секунду.
Оскільки наш пул потоків в середині клієнта = 50, а дані додаються в пуп без затримки то ми попросту досягли ліміту по з'єднанях, причому такого роду помилка обробляються в середині клієнта і запит буде повторено так як кількість повторів = 2.
Запити були повторені та всеодно 22 повідомлення так і не зашифрувалися , одже 22 реквеста були не вдалі а значить і наша конфігурація теж. (Доречі, 50 це число пулу в клієнті що встановлюється по замовчуванню якщо його не задавати при створенні)
Міняємо налаштування, мабуть всі скажуть що замало повторних спроб, ОК , ставимо більше :
Запускаємо наш тестовий стенд з розміром пула потоків 50 та кількісттю повторних спроб 3 :
- 1000 повідомлень успішно зашифровані;
- 983 повідомлення успішно розшифровано;
- 27 повідомлень не було розшифровано успішно;
- Те саме повідомлення в консолі.
Збільшуємо кількість повторів знову? - Вважаю це хибним, адже повторна спроба це і теоретично погано і практично б'є по швидкодії.
Пропуную зменшити розмір пула потоків і повернути кількість спроб назад:
Запускаємо наш тестовий стенд з розміром пула потоків 20 та кількісттю повторних спроб 2 :
- 999 повідомлень успішно зашифровані;
- 1 повідомлення не було успішно зашифровано;
Зменшуємо далі :
Запускаємо наш тестовий стенд з розміром пула потоків 10 та кількісттю повторних спроб 2 :
- 1000 повідомлень успішно зашифровані;
- 1000 повідомлень успішно розшифровано.
Юххууу... отже конфігурацію знайшли, проте коли я запускав ту ж роботу тільки від кількох потоків (а ми знаємо що пул клієнта буде 1 для всіх) то проблеми виникали але дуже рідко , що змусило підняти кількість спроб до 3, далі усе було ідеально.
Чи впливає маленьких розмір пула на час виконання всіх операції загалом в порівнянні з більшим розміром? - так алетести показали що ця різниця = 10 мілісекунд і не є суттєвою в мому випадку. Для економію часу не буду наводити дані тесту швидкодії проте найоптимальніша на мій погляд конфігурація дає такий результат :
Кількість потоків - 1, Розмір пулу в клієнта - 10, кількість повторів - 3 :
Encryption time for 1000 items (MILLISECONDS) : 8515
Errors happened on encryption cycle : 0
Decryption time for 1000 items (MILLISECONDS) : 10828
Errors happened on decryption cycle : 0
GENERAL TIME TO ENCRYPT 1000 AND DECRYPT 1000 items (MILLISECONDS) : 19343
20 секунд на все про все , думаю хороший результат =) .
Ціни
В цій статті буде використовуватись клієнт з підтримкою паралельних операцій.
Підготовка проекту
Для того щоб почати працювати з KMS треба підключити AWS SDK до проекту , я використовую наступно залежність у моєму Apache Maven проекті :
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.10.51</version>
</dependency>
Створення клієнта
Перш ніж створити клієнт і почати роботу потрібно ініціалізувати AWS креденшили, які клієнт приймає в конструкторі. Існує кілька способів отримати ці креденшили, можна імплементувати провайдер, і вже в середині вирішувати звідки отримати дані або ж просто ініціалізувати їх в коді, що ми і зробимо :
AWSCredentials awsCredentials = new AWSCredentials() {
public String getAWSAccessKeyId() {
return AWS_ACCESS_KEY_ID;
}
public String getAWSSecretKey() {
return AWS_SECRET_KEY;
}
};
Далі потрібно створити конфігурацію для нашого клієнта, звісно можна обійтися без неї (в середині і так використається конфігурація по замовчуванню). Нам вона потрібена лише щоб переконфігурувати політику ретраїв (повторних спроб), оскільки KMS має певні рестрікшени (100 реквестів в секунду на запити encrypt/decrypt та ін. одночасно) а ми використовуємо асинхронний клієнт, тому нам потрібно обробляти випадки коли виходимо за цей ліміт а також інші випадки при яких в асинхронному режимі варто повторити операцію (спершу я обробляв всі еррори і робив операції повторно в хендлері реквеста без цієї конфігурації, проте це не вірно, є випадки, наприклад: "дешифрування не валідних даних", які повторювати не треба). Сам клієнт вже має можливість повторювати певного роду помилки при роботі але по замовчуванню це вимкнено.
Отже створюємо конфігурацію і задаємо кількість повторів (далі ми будемо визначати оптимальну кількість потоків в екзекютері нашого клієнта , адже чим більше потоків і даних тим більше треба буде повторів і тим гірший буде перформенс) :
ClientConfiguration clientConfiguration = PredefinedClientConfigurations.defaultConfig();
clientConfiguration.setMaxErrorRetry(1);
Наразі встановимо кількість повторів рівною 1.
Маючи все що описано вище можна ініціалізувати KMS клієнт :
AWSKMSAsyncClient awsKmsClient = new AWSKMSAsyncClient(awsCredentials, clientConfiguration,
Executors.newFixedThreadPool(50));
В створеному клієнті ми використали наші AWS креденшили та конфігурацію, а також передали ExecutorService. Розмір пулу 50 є розміром по замовчуванню.
Шлях до AWS
Amazon має багато дата-центрів по всій планеті і всі вони мають різні зони доступу (availability zone) тому і шлях потібно вказувати додатковим параметром :
awsKmsClient.setEndpoint(AWS_ENDPOINT);
Для прикладу, шаблон шляху є таким : "https://kms.<availability_zone>.amazonaws.com", де <availability_zone> може бути: "eu-central-1".
Створення ключа для шифрування
Для шифрування даних нам потрібно використовувати Encryption Key Id (Id ключа шифрування). Щоб створити цей ключ і дізнатися його ID можна скористатися нашим KMS клієнтом або через Веб консоль AWS. Я користувався AWS веб консоллю і для того, щоб це зробити потрібно піти по наступному шляху :
Маючи все попереднє можна сміло приступати до шифрування / розшифрування даних.
Шифруємо (Data Encryption)
Для шифрування даних потрібно створити EnryptRequest і передати його на виконання нашому AWSKMSAsyncClient'у :
EncryptRequest encryptRequest = new EncryptRequest();
encryptRequest.setKeyId(KMS_KEY_ID);
encryptRequest.setPlaintext(ByteBuffer.wrap("This is text message".getBytes()));
В методі "setKeyId" використовуємо ID ключа а в метод "setPlaintext" передаємо байт-буфер даних котрі шифруються, в мому випадку це проста текстова стрічка. Також АРІ об'єкта EncryptRequest дозволяє створити його за допомогою білдера :
EncryptRequest encryptRequest = new EncryptRequest().withKeyId(KMS_KEY_ID).withPlaintext(ByteBuffer.wrap("This is text message".getBytes()));
byte[] encryptedData = null;
awsKmsClient.encryptAsync(encryptRequest,
new AsyncHandler<EncryptRequest, EncryptResult>() {
public void onError(Exception e) {
//error
}
public void onSuccess(EncryptRequest request, EncryptResult encryptResult) {
// get encrypted data bytes from ByteBuffer
encryptedData = encryptResult.getCiphertextBlob().array();
}
});
Оскільки я використовую клієнт з паралельною обробкою мені потрібно обробити результат виконання обробником або ж зберегти отриманий після виконання методу "encryptAsync" об'єкт Future<EncryptResult> і дочекавшись його значення отримати бажаний результат. Як показано вище, я використав обробник і в методі "onSuccess" вичитую ByteBuffer а вже з нього беру байти закодованого повідомлення. Метод "onFailure" я тут не чіпаю, хоча з даним підходом (коли ми використали Retry Policy клієнта) можна сказати що якщо цей метод викличеться то можна сміло фейлити операцію і логувати екзепшен (раніше я пробував тут повторно виконувати шифрування, та це не є правильним адже спрацювати він може через те, наприклад, що ключа яким шифруєте нема).
Розшифровуємо (Data Decryption)
Для того щоб розшифрувати наше повідомлення також потрібно створити запит :
DecryptRequest decryptRequest = new DecryptRequest().withCiphertextBlob(ByteBuffer.wrap(encryptedData));
Як бачите, для розшифрування повідомлення не потрібно вказувати ID ключа. А все тому, що зашифровані дані містять в собі мета-дані за допомогою яких відбувається розшифрування.
Запускаємо цей запит на виконання:
String result = null;
awsKmsClient.decryptAsync(decryptRequest,
new AsyncHandler<DecryptRequest, DecryptResult>() {
public void onError(Exception e) {
//error
}
public void onSuccess(DecryptRequest request, DecryptResult decryptResult) {
byte[] data = decryptResult.getPlaintext().array();
result = new String(data);
}
});
Аналогічно шифруванню, тут я використовує обробник. Як тільки виконається метод "onSuccess" я дістаю байти повідомлення і перетворюю в стрінгу.
Усе вище працює без проблем. Загалом схему шифрування та дешифрування можна зобрадити так :
Проблеми зі збереженням шифрованих даних у форматі String
Моя задача передбачала що дані (шифровані чи ні) передаються і зберігаються у форматі String. А String має конструктор що приймає масив байтів, тому паємо щойно зашифровані дані в стрінгу і зберігаємо (чи передаємо). Проте як тільки ми спробуємо перетворити стрінгу назад в байти і розшифрувати, ми отримаємо екзепшен з повідомленням :
Service: AWSKMS; Status Code: 400; Error Code: InvalidCiphertextException; Request ID: <your_request_id>
А все тому, що байти отримані з об'єкта String є "поломаними" і AWS KMS не може їх провалідувати і розшифрувати.
Моє розуміння проблеми наступне: - Коли зашифрований масив байтів (отриманий з відповіді KMS клієнта) приводиться до об'єкту String (за допомогою його конструктора) тоді і відбувається кораптання даних. Всім відомо що String має кодування по замовчуванню рівне "UTF-8" а це від 4 до 6 байтів на символ, реально ж використовуються символи тільки до 2 в 21 сепені (знайшов на вікіпедії), а як веде себе String коли зустрічає код символу що перевищує це число ? Хоча може в цей момент шифровані дані ще не "поломані", проте коли дану String'у привести назад в масив байтів щоб розшифрувати - точно "поломані".
Нажаль я глибоко в цю проблему не закопувався, тому якщо хтось розуміється краще, я буду дуже вдячний за коментарі.
Що робити ?
На просторах інтернету був знайдений солюшен - перетворити шифровані дані в формат Base64 :
byte[] encoded = Base64.encodeBase64(data);
Для цього було використано утиліту з пакету Apache Commons.
Отриманий після цього масив байтів можна спокійно приводити до об'єкту String і зберігати, надсилати чи що кому треба. Насправді навіть порівнюючи (при виводі) стрінгу створену з масиву байт шифрованих KMS'ом і стрінгу створену з тих же даних тільки перетворених у Base64 було чітко видно що стрінга першого варіанту взагалі була не "валідною" - містила пусті символи (підозрюю просто не відображалися) та якісь ієрогліфи, а друга стрінга була просто хаотичним набором латинських літер та символів, що зарактерно для відображення будь-якої захифрованої інформації.
Звісно треба не забути що в такому випадку для розшиврування даних потрібно їх привезти з Base64 у нормальний вигляд :
byte[] decoded = Base64.decodeBase64(data);
І вже цей набір байтів розшифровувати за допомогою KMS.
Звісно це лише мій випадок, коли я зберагаю у форматі String, якщо у вас є можливість зберігати це як маисв байтів або blob об'єкт то цього не потрібно.
Тестування в одному потоці та пошук оптимальних значень повторів та розміру пула потоків для клієнта
Для визначення найоптимальніших налаштуванн KMS клієнта поставимо наступні умови :
- Зашифрувати 1000 повідомлень;
- Розшифрувати 1000 повідомлень.
Отже запускаємо наш тестовий стенд (посилання на вихідний код буде в кінці) з розміром пула потоків 50 та кількісттю повторних спроб 2 :
- 978 повідомлень успішно зашифровані;
- 22 повідомлення не було зашифровано успішно;
- Аплікація не дойшла до розшифрування так як не всі повідомлення зашифрувалися;
- Ось таке повідомлення в консолі :
You have exceeded the rate at which you may call KMS. Reduce the frequency of your calls. (Service: AWSKMS; Status Code: 400; Error Code: ThrottlingException; Request ID: <your_request_id>
Що сталося?
AWS KMS має ліміти на з'єднання, для encrypt i decrypt операції це 100 запитів в секунду.
Оскільки наш пул потоків в середині клієнта = 50, а дані додаються в пуп без затримки то ми попросту досягли ліміту по з'єднанях, причому такого роду помилка обробляються в середині клієнта і запит буде повторено так як кількість повторів = 2.
Запити були повторені та всеодно 22 повідомлення так і не зашифрувалися , одже 22 реквеста були не вдалі а значить і наша конфігурація теж. (Доречі, 50 це число пулу в клієнті що встановлюється по замовчуванню якщо його не задавати при створенні)
Міняємо налаштування, мабуть всі скажуть що замало повторних спроб, ОК , ставимо більше :
Запускаємо наш тестовий стенд з розміром пула потоків 50 та кількісттю повторних спроб 3 :
- 1000 повідомлень успішно зашифровані;
- 983 повідомлення успішно розшифровано;
- 27 повідомлень не було розшифровано успішно;
- Те саме повідомлення в консолі.
Збільшуємо кількість повторів знову? - Вважаю це хибним, адже повторна спроба це і теоретично погано і практично б'є по швидкодії.
Пропуную зменшити розмір пула потоків і повернути кількість спроб назад:
Запускаємо наш тестовий стенд з розміром пула потоків 20 та кількісттю повторних спроб 2 :
- 999 повідомлень успішно зашифровані;
- 1 повідомлення не було успішно зашифровано;
Зменшуємо далі :
Запускаємо наш тестовий стенд з розміром пула потоків 10 та кількісттю повторних спроб 2 :
- 1000 повідомлень успішно зашифровані;
- 1000 повідомлень успішно розшифровано.
Юххууу... отже конфігурацію знайшли, проте коли я запускав ту ж роботу тільки від кількох потоків (а ми знаємо що пул клієнта буде 1 для всіх) то проблеми виникали але дуже рідко , що змусило підняти кількість спроб до 3, далі усе було ідеально.
Чи впливає маленьких розмір пула на час виконання всіх операції загалом в порівнянні з більшим розміром? - так алетести показали що ця різниця = 10 мілісекунд і не є суттєвою в мому випадку. Для економію часу не буду наводити дані тесту швидкодії проте найоптимальніша на мій погляд конфігурація дає такий результат :
Кількість потоків - 1, Розмір пулу в клієнта - 10, кількість повторів - 3 :
Encryption time for 1000 items (MILLISECONDS) : 8515
Errors happened on encryption cycle : 0
Decryption time for 1000 items (MILLISECONDS) : 10828
Errors happened on decryption cycle : 0
GENERAL TIME TO ENCRYPT 1000 AND DECRYPT 1000 items (MILLISECONDS) : 19343
20 секунд на все про все , думаю хороший результат =) .
Ціни
Відомо що Amazon заробляє на всіх своїх сервісах. Нижче наведена цінова політика на момент написання статті:
- Перші 20 000 реквестів у місяць безкоштовно (Encrypt / Decrypt / Create Key / Delete Key);
- Настіпні 10 000 реквестів після використаних безкоштовних будуть коштувати 0.3 центи;
- За зберігання ключа стягуватиметься 1 долар в місяць
Сорси проекту тут
Дякую усім за увагу!
- Перші 20 000 реквестів у місяць безкоштовно (Encrypt / Decrypt / Create Key / Delete Key);
- Настіпні 10 000 реквестів після використаних безкоштовних будуть коштувати 0.3 центи;
- За зберігання ключа стягуватиметься 1 долар в місяць
Сорси проекту тут
Дякую усім за увагу!