From Crippled Teal, 5 Years ago, written in Plain Text.
Embed
  1. package com.fosspowered.peist.service;
  2.  
  3. import com.fosspowered.peist.model.dao.Paste;
  4. import com.fosspowered.peist.model.exceptions.PeistAccessDeniedException;
  5. import com.fosspowered.peist.model.exceptions.PeistInternalException;
  6. import com.fosspowered.peist.model.exceptions.PeistInvalidRequestException;
  7. import com.fosspowered.peist.model.exceptions.PeistNotFoundException;
  8. import com.fosspowered.peist.model.json.PasteRequest;
  9. import com.fosspowered.peist.model.json.PasteResponse;
  10. import com.fosspowered.peist.repository.PasteRepository;
  11. import java.nio.charset.StandardCharsets;
  12. import java.security.InvalidKeyException;
  13. import java.security.MessageDigest;
  14. import java.security.NoSuchAlgorithmException;
  15. import java.sql.Date;
  16. import java.util.ArrayList;
  17. import java.util.Base64;
  18. import java.util.Calendar;
  19. import java.util.List;
  20. import java.util.Optional;
  21. import java.util.UUID;
  22. import java.util.stream.Collectors;
  23. import javax.crypto.BadPaddingException;
  24. import javax.crypto.Cipher;
  25. import javax.crypto.IllegalBlockSizeException;
  26. import javax.crypto.NoSuchPaddingException;
  27. import javax.crypto.spec.SecretKeySpec;
  28. import lombok.extern.log4j.Log4j2;
  29. import org.apache.commons.lang3.StringUtils;
  30. import org.springframework.beans.factory.annotation.Value;
  31. import org.springframework.stereotype.Service;
  32.  
  33. @Service
  34. @Log4j2
  35. public class PasteService {
  36.   private final PasteRepository pasteRepository;
  37.  
  38.   private final String systemKey;
  39.  
  40.   PasteService(PasteRepository pasteRepository, @Value("${system-key}") String systemKey) {
  41.     this.pasteRepository = pasteRepository;
  42.     this.systemKey = systemKey;
  43.   }
  44.  
  45.   public PasteResponse addPaste(PasteRequest request) {
  46.     Paste paste = buildPasteData(request);
  47.     this.pasteRepository.save(paste);
  48.     return buildPasteResponse(paste);
  49.   }
  50.  
  51.   private String convertToCipher(Date creationDate, String key, String text) {
  52.     SecretKeySpec keySpec = buildSpec(creationDate, key);
  53.     try {
  54.       Cipher cipher = Cipher.getInstance("AES");
  55.       cipher.init(Cipher.ENCRYPT_MODE, keySpec);
  56.       byte[] cipherBytes = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
  57.       return Base64.getEncoder().encodeToString(cipherBytes);
  58.     } catch (InvalidKeyException
  59.         | IllegalBlockSizeException
  60.         | BadPaddingException
  61.         | NoSuchAlgorithmException
  62.         | NoSuchPaddingException e) {
  63.       throw new RuntimeException(e);
  64.     }
  65.   }
  66.  
  67.   private String convertFromCipher(Date creationDate, String key, String cipherText) {
  68.     SecretKeySpec keySpec = buildSpec(creationDate, key);
  69.  
  70.     try {
  71.       Cipher cipher = Cipher.getInstance("AES");
  72.       cipher.init(Cipher.DECRYPT_MODE, keySpec);
  73.       return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
  74.     } catch (BadPaddingException e) {
  75.       throw new PeistAccessDeniedException("Access denied for paste.");
  76.     } catch (NoSuchAlgorithmException
  77.         | InvalidKeyException
  78.         | NoSuchPaddingException
  79.         | IllegalBlockSizeException e) {
  80.       log.error("Error while processing", e);
  81.       throw new PeistInternalException("Error while processing");
  82.     }
  83.   }
  84.  
  85.   private SecretKeySpec buildSpec(Date creationDate, String key) {
  86.     String keyStr =
  87.         String.format(
  88.             "%s%s%s", systemKey, StringUtils.isNotBlank(key) ? key : "", creationDate.getTime());
  89.     try {
  90.       MessageDigest sha = MessageDigest.getInstance("SHA-256");
  91.       return new SecretKeySpec(sha.digest(keyStr.getBytes(StandardCharsets.UTF_8)), "AES");
  92.     } catch (NoSuchAlgorithmException e) {
  93.       throw new RuntimeException(e);
  94.     }
  95.   }
  96.  
  97.   public PasteResponse fetchPaste(String urlId) {
  98.     return fetchPaste(urlId, null);
  99.   }
  100.  
  101.   public PasteResponse fetchPaste(String urlId, String key) {
  102.     Paste paste = fetchPasteFromDB(urlId);
  103.     String text = convertFromCipher(paste.getCreationDate(), key, paste.getPasteData());
  104.     paste.setPasteData(text);
  105.     return buildPasteResponse(paste);
  106.   }
  107.  
  108.   private Paste fetchPasteFromDB(String urlId) {
  109.     if (StringUtils.isBlank(urlId)) {
  110.       throw new PeistInvalidRequestException("Invalid request as urlId is invalid: " + urlId);
  111.     }
  112.     Optional<Paste> paste = this.pasteRepository.findByUrlId(urlId);
  113.     if (paste.isPresent()) {
  114.       return paste.get();
  115.     } else {
  116.       throw new PeistNotFoundException("Paste not found for urlId: " + urlId);
  117.     }
  118.   }
  119.  
  120.   public List<PasteResponse> fetchRecentPastes() {
  121.     List<Paste> pasteList = new ArrayList<>(this.pasteRepository.findAll());
  122.     return pasteList.stream().map(this::buildPasteResponse).collect(Collectors.toList());
  123.   }
  124.  
  125.   private PasteResponse buildPasteResponse(Paste paste) {
  126.  
  127.     return PasteResponse.builder()
  128.         .urlId(paste.getUrlId())
  129.         .creationDate(paste.getCreationDate())
  130.         .author(paste.getAuthor())
  131.         .language(paste.getLanguage())
  132.         .title(paste.getTitle())
  133.         .expiryDate(paste.getExpiryDate())
  134.         .isVisible(paste.getIsVisible())
  135.         .pasteData(paste.getPasteData())
  136.         .build();
  137.   }
  138.  
  139.   private Paste buildPasteData(PasteRequest pasteRequest) {
  140.     Calendar now = Calendar.getInstance();
  141.     Date creationDate = new Date(now.getTime().getTime());
  142.     now.add(Calendar.SECOND, pasteRequest.getTtl());
  143.     Date expiryDate = new Date(now.getTime().getTime());
  144.  
  145.     String secretKey = pasteRequest.getSecretKey();
  146.     boolean isVisible = StringUtils.isNotBlank(pasteRequest.getSecretKey());
  147.     String text = convertToCipher(creationDate, secretKey, pasteRequest.getPasteData());
  148.  
  149.     Paste paste = new Paste();
  150.     paste.setUrlId(UUID.randomUUID().toString());
  151.     paste.setCreationDate(creationDate);
  152.     paste.setTitle(pasteRequest.getTitle());
  153.     paste.setAuthor(pasteRequest.getAuthor());
  154.     paste.setLanguage(pasteRequest.getLanguage());
  155.     paste.setExpiryDate(expiryDate);
  156.     paste.setIsVisible(isVisible);
  157.     paste.setPasteData(text);
  158.     return paste;
  159.   }
  160. }
  161.  

Replies to Untitled rss

Title Name Language When
Re: Untitled Subtle Horse text 5 Years ago.