code: @CheckForNull
      public static Secret decrypt(@CheckForNull String data) {
          if(!isValidData(data))      return null;
  
          if (data.startsWith("{") && data.endsWith("}")) { //likely CBC encrypted/containing metadata but could be plain text
              byte[] payload;
              try {
                  payload = Base64.getDecoder().decode(data.substring(1, data.length()-1));
              } catch (IllegalArgumentException e) {
                  return null;
              }
              switch (payload[0]) {
                  case PAYLOAD_V1:
                      // For PAYLOAD_V1 we use this byte shifting model, V2 probably will need DataOutput
                      int ivLength = ((payload[1] & 0xff) << 24)
                              | ((payload[2] & 0xff) << 16)
                              | ((payload[3] & 0xff) << 8)
                              | (payload[4] & 0xff);
                      int dataLength = ((payload[5] & 0xff) << 24)
                              | ((payload[6] & 0xff) << 16)
                              | ((payload[7] & 0xff) << 8)
                              | (payload[8] & 0xff);
                      if (payload.length != 1 + 8 + ivLength + dataLength) {
                          // not valid v1
                          return null;
                      }
                      byte[] iv = Arrays.copyOfRange(payload, 9, 9 + ivLength);
                      byte[] code = Arrays.copyOfRange(payload, 9+ivLength, payload.length);
                      String text;
                      try {
                          text = new String(KEY.decrypt(iv).doFinal(code), UTF_8);
                      } catch (GeneralSecurityException e) {
                          // it's v1 which cannot be historical, but not decrypting
                          return null;
                      }
                      return new Secret(text, iv);
                  default:
                      return null;
              }
          } else {
              try {
                  return HistoricalSecrets.decrypt(data, KEY);
              } catch (UnsupportedEncodingException e) {
                  throw new Error(e); // impossible
              } catch (GeneralSecurityException | IOException e) {
                  return null;
              }
          }
      }
docs: Reverse operation of {@link #getEncryptedValue()}. Returns null
  if the given cipher text was invalid.