예제 #1
0
 /**
  * Set the key files for {@link #buildNextKeyMapPart()}. Key duplicates from the key file will be
  * removed.
  *
  * @param keyFiles One or more key files. These files are simple text files with one key per line.
  *     Empty lines and lines STARTING with "#" will not be interpreted.
  * @param context The context in which the possible "Out of memory"-Toast will be shown.
  * @return True if the key files are correctly loaded. False on error (out of memory).
  */
 public boolean setKeyFile(File[] keyFiles, Context context) {
   HashSet<byte[]> keys = new HashSet<byte[]>();
   for (File file : keyFiles) {
     String[] lines = Common.readFileLineByLine(file, false, context);
     if (lines != null) {
       for (String line : lines) {
         if (!line.equals("") && line.length() == 12 && line.matches("[0-9A-Fa-f]+")) {
           try {
             keys.add(Common.hexStringToByteArray(line));
           } catch (OutOfMemoryError e) {
             // Error. Too many keys (out of memory).
             Toast.makeText(context, R.string.info_to_many_keys, Toast.LENGTH_LONG).show();
             return false;
           }
         }
       }
     }
   }
   if (keys.size() > 0) {
     mKeysWithOrder = new ArrayList<byte[]>(keys);
   }
   return true;
 }
예제 #2
0
  /**
   * Read a as much as possible from a sector with the given key. Best results are gained from a
   * valid key B (except key B is marked as readable in the access conditions).
   *
   * @param sectorIndex Index of the Sector to read. (For Mifare Classic 1K: 0-63)
   * @param key Key for the authentication.
   * @param useAsKeyB If true, key will be treated as key B for authentication.
   * @return Array of blocks (index 0-3 or 0-15). If a block or a key is marked with {@link
   *     #NO_DATA} or {@link #NO_KEY} it means that this data could be read or found. On
   *     authentication error "null" will be returned.
   * @throws TagLostException When tag is lost.
   * @see #mergeSectorData(String[], String[])
   */
  public String[] readSector(int sectorIndex, byte[] key, boolean useAsKeyB)
      throws TagLostException {
    boolean auth = authenticate(sectorIndex, key, useAsKeyB);
    String[] ret = null;
    // Read sector.
    if (auth) {
      // Read all blocks.
      ArrayList<String> blocks = new ArrayList<String>();
      int firstBlock = mMFC.sectorToBlock(sectorIndex);
      int lastBlock = firstBlock + 4;
      if (mMFC.getSize() == MifareClassic.SIZE_4K && sectorIndex > 31) {
        lastBlock = firstBlock + 16;
      }
      for (int i = firstBlock; i < lastBlock; i++) {
        try {
          byte blockBytes[] = mMFC.readBlock(i);
          // mMFC.readBlock(i) must return 16 bytes or throw an error.
          // At least this is what the documentation says.
          // On Samsungs Galaxy S5 however, it sometimes
          // returns < 16 bytes for unknown reasons.
          if (blockBytes.length != 16) {
            throw new IOException();
          }
          blocks.add(Common.byte2HexString(blockBytes));
        } catch (TagLostException e) {
          throw e;
        } catch (IOException e) {
          // Could not read block.
          // (Maybe due to key/authentication method.)
          Log.d(LOG_TAG, "Error while reading block " + i + " from tag.");
          blocks.add(NO_DATA);
          if (!mMFC.isConnected()) {
            throw new TagLostException("Tag removed during readSector(...)");
          }
          // After error reauthentication is needed.
          auth = authenticate(sectorIndex, key, useAsKeyB);
        }
      }
      ret = blocks.toArray(new String[blocks.size()]);
      int last = ret.length - 1;

      // Merge key in last block (sector trailer).
      if (!useAsKeyB) {
        if (isKeyBReadable(Common.hexStringToByteArray(ret[last].substring(12, 20)))) {
          ret[last] = Common.byte2HexString(key) + ret[last].substring(12, 32);
        } else {
          ret[last] = Common.byte2HexString(key) + ret[last].substring(12, 20) + NO_KEY;
        }
      } else {
        if (ret[0].equals(NO_DATA)) {
          // If Key B may be read in the corresponding Sector Trailer,
          // it cannot serve for authentication (according to NXP).
          // What they mean is that you can authenticate successfully,
          // but can not read data. In this case the
          // readBlock() result is 0 for each block.
          ret = null;
        } else {
          ret[last] = NO_KEY + ret[last].substring(12, 20) + Common.byte2HexString(key);
        }
      }
    }
    return ret;
  }