コード例 #1
0
ファイル: FileUtils.cpp プロジェクト: HirasawaRUS/encfs4win
        void save(Archive &ar, const EncFSConfig &cfg, 
                unsigned int version)
        {
            (void)version;
            // version 20 (aka 20100613)
            if (cfg.subVersion == 0)
                ar << make_nvp("version", V6SubVersion);
            else
                ar << make_nvp("version", cfg.subVersion);

            ar << make_nvp("creator", cfg.creator);
            ar << make_nvp("cipherAlg", cfg.cipherIface);
            ar << make_nvp("nameAlg", cfg.nameIface);
            ar << make_nvp("keySize", cfg.keySize);
            ar << make_nvp("blockSize", cfg.blockSize);
            ar << make_nvp("uniqueIV", cfg.uniqueIV);
            ar << make_nvp("chainedNameIV", cfg.chainedNameIV);
            ar << make_nvp("externalIVChaining", cfg.externalIVChaining);
            ar << make_nvp("blockMACBytes", cfg.blockMACBytes);
            ar << make_nvp("blockMACRandBytes", cfg.blockMACRandBytes);
            ar << make_nvp("allowHoles", cfg.allowHoles);

            int encodedSize = cfg.keyData.size();
            ar << make_nvp("encodedKeySize", encodedSize);
            ar << make_nvp("encodedKeyData",
                    serial::make_binary_object(cfg.getKeyData(), encodedSize));

            // version 20080816
            int size = cfg.salt.size();
            ar << make_nvp("saltLen", size);
            ar << make_nvp("saltData",
                    serial::make_binary_object(cfg.getSaltData(), size));
            ar << make_nvp("kdfIterations", cfg.kdfIterations);
            ar << make_nvp("desiredKDFDuration", cfg.desiredKDFDuration);
        }
コード例 #2
0
ファイル: test.cpp プロジェクト: Aikhjarto/encfs
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
{
    // create a random key
    if(verbose)
	cerr << "Generating new key, output will be different on each run\n\n";
    CipherKey key = cipher->newRandomKey();

    if(verbose)
	cerr << "Testing key save / restore :";
    {
	CipherKey encodingKey = cipher->newRandomKey();
	int encodedKeySize = cipher->encodedKeySize();
	unsigned char *keyBuf = new unsigned char [ encodedKeySize ];

	cipher->writeKey( key, keyBuf, encodingKey );
	CipherKey key2 = cipher->readKey( keyBuf, encodingKey );
	if(!key2)
	{
	    if(verbose)
		cerr << "   FAILED (decode error)\n";
	    return false;
	}

	if(cipher->compareKey( key, key2 ))
	{
	    if(verbose)
	       	cerr << "   OK\n";
	} else
	{
	    if(verbose)
		cerr << "   FAILED\n";
	    return false;
	}
    }
    
    if(verbose)
	cerr << "Testing Config interface load / store :";
    {
	CipherKey encodingKey = cipher->newRandomKey();
	int encodedKeySize = cipher->encodedKeySize();
	unsigned char *keyBuf = new unsigned char [ encodedKeySize ];

	cipher->writeKey( key, keyBuf, encodingKey );

	// store in config struct..
	EncFSConfig cfg;
	cfg.cipherIface = cipher->interface();
	cfg.keySize = 8 * cipher->keySize();
	cfg.blockSize = FSBlockSize;
	cfg.assignKeyData( keyBuf, encodedKeySize );

	// save config
        string data;
        {
            ostringstream st;
            st << cfg;
            data = st.str();
        }

	// read back in and check everything..
        EncFSConfig cfg2;
        {
            istringstream st(data);
            st >> cfg2;
        }

	// check..
	rAssert( cfg.cipherIface.implements(cfg2.cipherIface) );
	rAssert( cfg.keySize == cfg2.keySize );
	rAssert( cfg.blockSize == cfg2.blockSize );

	// try decoding key..

	CipherKey key2 = cipher->readKey( cfg2.getKeyData(), encodingKey );
	if(!key2)
	{
	    if(verbose)
		cerr << "   FAILED (decode error)\n";
	    return false;
	}

	if(cipher->compareKey( key, key2 ))
	{
	    if(verbose)
	       	cerr << "   OK\n";
	} else
	{
	    if(verbose)
		cerr << "   FAILED\n";
	    return false;
	}
    }

    FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
    fsCfg->cipher = cipher;
    fsCfg->key = key;
    fsCfg->config.reset(new EncFSConfig);
    fsCfg->config->blockSize = FSBlockSize;

    if(verbose)
	cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
    {
        fsCfg->opts.reset(new EncFS_Opts);
        fsCfg->opts->idleTracking = false;
        fsCfg->config->uniqueIV = false;

        fsCfg->nameCoding.reset( new StreamNameIO(
		    StreamNameIO::CurrentInterface(), cipher, key ) );
        fsCfg->nameCoding->setChainedNameIV( true );

        DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );

	if(!testNameCoding( dirNode, verbose ))
	    return false;
    }
    
    if(verbose)
	cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
    {
        fsCfg->opts->idleTracking = false;
        fsCfg->config->uniqueIV = false;
        fsCfg->nameCoding.reset( new BlockNameIO(
		    BlockNameIO::CurrentInterface(), cipher, key,
		    cipher->cipherBlockSize() ) );
        fsCfg->nameCoding->setChainedNameIV( true );
	
        DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );

	if(!testNameCoding( dirNode, verbose ))
	    return false;
    }
    
    if(verbose)
	cerr << "Testing name encode/decode (block coding w/ IV chaining, base32)\n";
    {
        fsCfg->opts->idleTracking = false;
        fsCfg->config->uniqueIV = false;
        fsCfg->nameCoding.reset( new BlockNameIO(
		    BlockNameIO::CurrentInterface(), cipher, key,
		    cipher->cipherBlockSize(), true ) );
        fsCfg->nameCoding->setChainedNameIV( true );
	
        DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );

	if(!testNameCoding( dirNode, verbose ))
	    return false;
    }
   
    if(!verbose)
    {
	{
	    // test stream mode, this time without IV chaining
            fsCfg->nameCoding =
		shared_ptr<NameIO>( new StreamNameIO( 
			    StreamNameIO::CurrentInterface(), cipher, key ) );
            fsCfg->nameCoding->setChainedNameIV( false );

            DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );

	    if(!testNameCoding( dirNode, verbose ))
	       	return false;
	}

	{
	    // test block mode, this time without IV chaining
            fsCfg->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
			BlockNameIO::CurrentInterface(), cipher, key,
			cipher->cipherBlockSize() ) );
            fsCfg->nameCoding->setChainedNameIV( false );

            DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );

	    if(!testNameCoding( dirNode, verbose ))
	       	return false;
	}
    }

    if(verbose)
       	cerr << "Testing block encode/decode on full block -  ";
    {
	int numErrors = checkErrorPropogation( cipher,
		FSBlockSize, -1, key );
	if(numErrors)
	{
	    if(verbose)
		cerr << " FAILED!\n";
	    return false;
	} else
	{
	    if(verbose)
	      	cerr << " OK\n";
	}
    }
    if(verbose)
       	cerr << "Testing block encode/decode on partial block -  ";
    {
	int numErrors = checkErrorPropogation( cipher,
		FSBlockSize-1, -1, key );
	if(numErrors)
	{
	    if(verbose)
	       	cerr << " FAILED!\n";
	    return false;
	} else
	{
	    if(verbose)
		cerr << " OK\n";
	}
    }

    if(verbose)
       	cerr << "Checking error propogation in partial block:\n";
    {
	int minChanges = FSBlockSize-1;
	int maxChanges = 0;
	int minAt = 0;
	int maxAt = 0;
	for(int i=0; i<FSBlockSize-1; ++i)
	{
	    int numErrors = checkErrorPropogation( cipher,
		    FSBlockSize-1, i, key );

	    if(numErrors < minChanges) 
	    {
		minChanges = numErrors;
		minAt = i;
	    }
	    if(numErrors > maxChanges)
	    {
		maxChanges = numErrors;
		maxAt = i;
	    }
	}

	if(verbose)
	{
    	    cerr << "modification of 1 byte affected between " << minChanges
    		<< " and " << maxChanges << " decoded bytes\n";
	    cerr << "minimum change at byte " << minAt
	       	<< " and  maximum at byte " << maxAt << "\n";
	}
    }
    if(verbose)
       	cerr << "Checking error propogation on full block:\n";
    {
	int minChanges = FSBlockSize;
	int maxChanges = 0;
	int minAt = 0;
	int maxAt = 0;
	for(int i=0; i<FSBlockSize; ++i)
	{
	    int numErrors = checkErrorPropogation( cipher,
		    FSBlockSize, i, key );

	    if(numErrors < minChanges) 
	    {
		minChanges = numErrors;
		minAt = i;
	    }
	    if(numErrors > maxChanges)
	    {
		maxChanges = numErrors;
		maxAt = i;
	    }
	}

	if(verbose)
	{
	    cerr << "modification of 1 byte affected between " << minChanges
	       	<< " and " << maxChanges << " decoded bytes\n";
	    cerr << "minimum change at byte " << minAt
		<< " and  maximum at byte " << maxAt << "\n";
	}
    }

    return true;
}
コード例 #3
0
ファイル: test.cpp プロジェクト: rfjakob/encfs
bool runTests(const std::shared_ptr<Cipher> &cipher, bool verbose) {
  // create a random key
  if (verbose) {
    cerr << "Generating new key, output will be different on each run\n\n";
  }
  CipherKey key = cipher->newRandomKey();

  if (verbose) cerr << "Testing key save / restore :";
  {
    CipherKey encodingKey = cipher->newRandomKey();
    int encodedKeySize = cipher->encodedKeySize();
    unsigned char keyBuf[encodedKeySize];

    cipher->writeKey(key, keyBuf, encodingKey);
    CipherKey key2 = cipher->readKey(keyBuf, encodingKey);
    if (!key2) {
      if (verbose) cerr << "   FAILED (decode error)\n";
      return false;
    }

    if (cipher->compareKey(key, key2)) {
      if (verbose) cerr << "   OK\n";
    } else {
      if (verbose) cerr << "   FAILED\n";
      return false;
    }
  }

  if (verbose) cerr << "Testing Config interface load / store :";
  {
    CipherKey encodingKey = cipher->newRandomKey();
    int encodedKeySize = cipher->encodedKeySize();
    unsigned char keyBuf[encodedKeySize];

    cipher->writeKey(key, keyBuf, encodingKey);

    // store in config struct..
    EncFSConfig cfg;
    cfg.cipherIface = cipher->interface();
    cfg.keySize = 8 * cipher->keySize();
    cfg.blockSize = FSBlockSize;
    cfg.assignKeyData(keyBuf, encodedKeySize);

    // save config
    // Creation of a temporary file should be more platform independent. On
    // c++17 we could use std::filesystem.
    string name = "/tmp/encfstestXXXXXX";
    int tmpFd = mkstemp(&name[0]);
    rAssert(-1 != tmpFd);
    // mkstemp opens the temporary file, but we only need its name -> close it
    rAssert(0 == close(tmpFd));
    {
      auto ok = writeV6Config(name.c_str(), &cfg);
      rAssert(ok == true);
    }

    // read back in and check everything..
    EncFSConfig cfg2;
    {
      auto ok = readV6Config(name.c_str(), &cfg2, nullptr);
      rAssert(ok == true);
    }
    // delete the temporary file where we stored the config
    rAssert(0 == unlink(name.c_str()));

    // check..
    rAssert(cfg.cipherIface.implements(cfg2.cipherIface));
    rAssert(cfg.keySize == cfg2.keySize);
    rAssert(cfg.blockSize == cfg2.blockSize);

    // try decoding key..

    CipherKey key2 = cipher->readKey(cfg2.getKeyData(), encodingKey);
    if (!key2) {
      if (verbose) cerr << "   FAILED (decode error)\n";
      return false;
    }

    if (cipher->compareKey(key, key2)) {
      if (verbose) cerr << "   OK\n";
    } else {
      if (verbose) cerr << "   FAILED\n";
      return false;
    }
  }

  FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
  fsCfg->cipher = cipher;
  fsCfg->key = key;
  fsCfg->config.reset(new EncFSConfig);
  fsCfg->config->blockSize = FSBlockSize;

  if (verbose)
    cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
  {
    fsCfg->opts.reset(new EncFS_Opts);
    fsCfg->opts->idleTracking = false;
    fsCfg->config->uniqueIV = false;

    fsCfg->nameCoding.reset(
        new StreamNameIO(StreamNameIO::CurrentInterface(), cipher, key));
    fsCfg->nameCoding->setChainedNameIV(true);

    DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);

    if (!testNameCoding(dirNode, verbose)) return false;
  }

  if (verbose)
    cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
  {
    fsCfg->opts->idleTracking = false;
    fsCfg->config->uniqueIV = false;
    fsCfg->nameCoding.reset(new BlockNameIO(BlockNameIO::CurrentInterface(),
                                            cipher, key,
                                            cipher->cipherBlockSize()));
    fsCfg->nameCoding->setChainedNameIV(true);

    DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);

    if (!testNameCoding(dirNode, verbose)) return false;
  }

  if (verbose)
    cerr
        << "Testing name encode/decode (block coding w/ IV chaining, base32)\n";
  {
    fsCfg->opts->idleTracking = false;
    fsCfg->config->uniqueIV = false;
    fsCfg->nameCoding.reset(new BlockNameIO(BlockNameIO::CurrentInterface(),
                                            cipher, key,
                                            cipher->cipherBlockSize(), true));
    fsCfg->nameCoding->setChainedNameIV(true);

    DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);

    if (!testNameCoding(dirNode, verbose)) return false;
  }

  if (!verbose) {
    {
      // test stream mode, this time without IV chaining
      fsCfg->nameCoding = std::shared_ptr<NameIO>(
          new StreamNameIO(StreamNameIO::CurrentInterface(), cipher, key));
      fsCfg->nameCoding->setChainedNameIV(false);

      DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);

      if (!testNameCoding(dirNode, verbose)) return false;
    }

    {
      // test block mode, this time without IV chaining
      fsCfg->nameCoding = std::shared_ptr<NameIO>(
          new BlockNameIO(BlockNameIO::CurrentInterface(), cipher, key,
                          cipher->cipherBlockSize()));
      fsCfg->nameCoding->setChainedNameIV(false);

      DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);

      if (!testNameCoding(dirNode, verbose)) return false;
    }
  }

  if (verbose) cerr << "Testing block encode/decode on full block -  ";
  {
    int numErrors = checkErrorPropogation(cipher, FSBlockSize, -1, key);
    if (numErrors) {
      if (verbose) cerr << " FAILED!\n";
      return false;
    } else {
      if (verbose) cerr << " OK\n";
    }
  }
  if (verbose) cerr << "Testing block encode/decode on partial block -  ";
  {
    int numErrors = checkErrorPropogation(cipher, FSBlockSize - 1, -1, key);
    if (numErrors) {
      if (verbose) cerr << " FAILED!\n";
      return false;
    } else {
      if (verbose) cerr << " OK\n";
    }
  }

  if (verbose) cerr << "Checking error propogation in partial block:\n";
  {
    int minChanges = FSBlockSize - 1;
    int maxChanges = 0;
    int minAt = 0;
    int maxAt = 0;
    for (int i = 0; i < FSBlockSize - 1; ++i) {
      int numErrors = checkErrorPropogation(cipher, FSBlockSize - 1, i, key);

      if (numErrors < minChanges) {
        minChanges = numErrors;
        minAt = i;
      }
      if (numErrors > maxChanges) {
        maxChanges = numErrors;
        maxAt = i;
      }
    }

    if (verbose) {
      cerr << "modification of 1 byte affected between " << minChanges
           << " and " << maxChanges << " decoded bytes\n";
      cerr << "minimum change at byte " << minAt << " and maximum at byte "
           << maxAt << "\n";
    }
  }
  if (verbose) cerr << "Checking error propogation on full block:\n";
  {
    int minChanges = FSBlockSize;
    int maxChanges = 0;
    int minAt = 0;
    int maxAt = 0;
    for (int i = 0; i < FSBlockSize; ++i) {
      int numErrors = checkErrorPropogation(cipher, FSBlockSize, i, key);

      if (numErrors < minChanges) {
        minChanges = numErrors;
        minAt = i;
      }
      if (numErrors > maxChanges) {
        maxChanges = numErrors;
        maxAt = i;
      }
    }

    if (verbose) {
      cerr << "modification of 1 byte affected between " << minChanges
           << " and " << maxChanges << " decoded bytes\n";
      cerr << "minimum change at byte " << minAt << " and maximum at byte "
           << maxAt << "\n";
    }
  }

  return true;
}
コード例 #4
0
ファイル: encfsctl.cpp プロジェクト: aidan-fitz/encfs
static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc,
                       char **argv) {
  (void)argc;
  string rootDir = argv[1];
  if (!checkDir(rootDir)) return EXIT_FAILURE;

  EncFSConfig *config = new EncFSConfig;
  ConfigType cfgType = readConfig(rootDir, config);

  if (cfgType == Config_None) {
    cout << _("Unable to load or parse config file\n");
    return EXIT_FAILURE;
  }

  // instanciate proper cipher
  std::shared_ptr<Cipher> cipher =
      Cipher::New(config->cipherIface, config->keySize);
  if (!cipher) {
    cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
                        config->cipherIface.name().c_str());
    return EXIT_FAILURE;
  }

  // ask for existing password
  cout << _("Enter current Encfs password\n");
  if (annotate) cerr << "$PROMPT$ passwd" << endl;
  CipherKey userKey = config->getUserKey(useStdin);
  if (!userKey) return EXIT_FAILURE;

  // decode volume key using user key -- at this point we detect an incorrect
  // password if the key checksum does not match (causing readKey to fail).
  CipherKey volumeKey = cipher->readKey(config->getKeyData(), userKey);

  if (!volumeKey) {
    cout << _("Invalid password\n");
    return EXIT_FAILURE;
  }

  if (checkOnly) {
    cout << _("Password is correct\n");
    return EXIT_SUCCESS;
  }

  // Now, get New user key..
  userKey.reset();
  cout << _("Enter new Encfs password\n");
  // reinitialize salt and iteration count
  config->kdfIterations = 0;  // generate new

  if (useStdin) {
    if (annotate) cerr << "$PROMPT$ new_passwd" << endl;
    userKey = config->getUserKey(true);
  } else
    userKey = config->getNewUserKey();

  // re-encode the volume key using the new user key and write it out..
  int result = EXIT_FAILURE;
  if (userKey) {
    int encodedKeySize = cipher->encodedKeySize();
    unsigned char *keyBuf = new unsigned char[encodedKeySize];

    // encode volume key with new user key
    cipher->writeKey(volumeKey, keyBuf, userKey);
    userKey.reset();

    config->assignKeyData(keyBuf, encodedKeySize);
    delete[] keyBuf;

    if (saveConfig(cfgType, rootDir, config)) {
      // password modified -- changes volume key of filesystem..
      cout << _("Volume Key successfully updated.\n");
      result = EXIT_SUCCESS;
    } else {
      cout << _("Error saving modified config file.\n");
    }
  } else {
    cout << _("Error creating key\n");
  }

  volumeKey.reset();

  return result;
}