// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT-0 package com.example.application; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; import java.time.Duration; import java.time.format.DateTimeFormatter; import java.util.Base64; import java.util.Random; //import org.apache.commons.lang3.RandomStringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import com.example.application.data.AppUser; import java.security.SecureRandom; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; public class CredentialUtility { private final static Logger logger = LogManager.getLogger(CredentialUtility.class); private static final String VALID_PW_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*?"; private static final int DEFAULT_PASSWORD_LENGTH = 12; private static final Random RANDOM = new SecureRandom(); private static final String region = System.getenv("AWS_REGION"); private static Region REGION = Region.of(region); private static String getPublicKeyAsString(KeyPair keyPair) throws NullPointerException { RSAPublicKey pub = (RSAPublicKey) keyPair.getPublic(); String publicKeyAsString = null; try { publicKeyAsString = encode(pub); } catch (UnsupportedEncodingException uee) { logger.error(uee.getMessage()); } catch (IOException io) { logger.error(io.getMessage()); } if (publicKeyAsString == null) { throw new NullPointerException("Something went wrong creating a public key"); } else { return publicKeyAsString; } } private static String getPrivateKeyAsString(KeyPair keyPair) { StringWriter privateWrite = new StringWriter(); JcaPEMWriter privatePemWriter = new JcaPEMWriter(privateWrite); try { privatePemWriter.writeObject(keyPair.getPrivate()); privatePemWriter.close(); } catch (IOException io) { logger.error(io.getMessage()); } return privateWrite.toString(); } public static KeyPair generateKeyPair() { java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyPair keyPair = null; try { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); keyPair = kpg.generateKeyPair(); } catch (NoSuchAlgorithmException e) { logger.error(e.getMessage()); } return keyPair; } private static String encode(RSAPublicKey key) throws IOException { ByteArrayOutputStream buf = new ByteArrayOutputStream(); byte[] name = "ssh-rsa".getBytes("US-ASCII"); write(name, buf); write(key.getPublicExponent().toByteArray(), buf); write(key.getModulus().toByteArray(), buf); // String s = new String(buf.toByteArray(), StandardCharsets.UTF_8); String s2 = "ssh-rsa " + Base64.getEncoder().encodeToString(buf.toByteArray()); return s2; } private static void write(byte[] str, OutputStream os) throws IOException { for (int shift = 24; shift >= 0; shift -= 8) os.write((str.length >>> shift) & 0xFF); os.write(str); } /* public static URL getPrivateKeyPresignedUrl(String s3Bucket, String s3Path) { S3Presigner presigner = S3Presigner.builder().region(REGION).build(); GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket(Toolkit.RESOURCE_BUCKET) .key(s3Path) .build(); GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofDays(7)) .getObjectRequest(getObjectRequest) .build(); PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest); URL url = presignedGetObjectRequest.url(); presigner.close(); return url; }*/ public static String[] uploadKeysToS3(KeyPair keyPair, AppUser appUser) { String[] keyPairObjectPaths = new String[2]; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); String timestamp = formatter.format(Toolkit.getSanDiegoTime()); String publicKeyFileName = appUser.getUsername() + "/public-keys/" + appUser.getUsername() + "_" + timestamp + ".pub"; S3Client s3 = Toolkit.getS3Client(); String privateKeyFileName = appUser.getUsername() + "/private-keys/" + appUser.getUsername() + "_" + timestamp + ".pem"; keyPairObjectPaths[0] = privateKeyFileName; keyPairObjectPaths[1] = publicKeyFileName; logger.info("Uploading public key " + publicKeyFileName + " to resource bucket"); logger.info("Uploading private key " + privateKeyFileName + " to resource bucket"); byte[] publicKeyArray = getPublicKeyAsString(keyPair).getBytes(); PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(Toolkit.RESOURCE_BUCKET) .key(publicKeyFileName) .build(); ByteBuffer byteBuffer = ByteBuffer.wrap(publicKeyArray); s3.putObject(objectRequest, RequestBody.fromByteBuffer(byteBuffer)); byte[] privateKeyArray = getPrivateKeyAsString(keyPair).getBytes(); PutObjectRequest objectRequest2 = PutObjectRequest.builder() .bucket(Toolkit.RESOURCE_BUCKET) .key(privateKeyFileName) .build(); ByteBuffer privateKeyByteBuffer = ByteBuffer.wrap(privateKeyArray); s3.putObject(objectRequest2, RequestBody.fromByteBuffer(privateKeyByteBuffer)); return keyPairObjectPaths; } /******/ /* * public static String generateCommonLangPassword() { * String upperCaseLetters = RandomStringUtils.random(2, 65, 90, true, true); * String lowerCaseLetters = RandomStringUtils.random(2, 97, 122, true, true); * String numbers = RandomStringUtils.randomNumeric(2); * String specialChar = RandomStringUtils.random(2, 33, 47, false, false); * String totalChars = RandomStringUtils.randomAlphanumeric(2); * String combinedChars = upperCaseLetters.concat(lowerCaseLetters) * .concat(numbers) * .concat(specialChar) * .concat(totalChars); * List<Character> pwdChars = combinedChars.chars() * .mapToObj(c -> (char) c) * .collect(Collectors.toList()); * Collections.shuffle(pwdChars); * String password = pwdChars.stream() * .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) * .toString(); * return password; * } */ // main class public static String generatePassword() { StringBuilder pw = new StringBuilder(); // generate password for (int i = 0; i < DEFAULT_PASSWORD_LENGTH; i++) { int index = RANDOM.nextInt(VALID_PW_CHARS.length()); pw.append(VALID_PW_CHARS.charAt(index)); } return pw.toString(); } }