Package com.subgraph.orchid.circuits.hs

Source Code of com.subgraph.orchid.circuits.hs.HSAuthentication$BasicAuthEntry

package com.subgraph.orchid.circuits.hs;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.subgraph.orchid.TorParsingException;
import com.subgraph.orchid.circuits.hs.HSDescriptorCookie.CookieType;
import com.subgraph.orchid.crypto.TorMessageDigest;
import com.subgraph.orchid.crypto.TorStreamCipher;

public class HSAuthentication {
  private final static int BASIC_ID_LENGTH = 4;
  private final HSDescriptorCookie cookie;
 
  public HSAuthentication(HSDescriptorCookie cookie) {
    this.cookie = cookie;
  }
 
  public byte[] decryptIntroductionPoints(byte[] content) throws HSAuthenticationException {
    final ByteBuffer buffer = ByteBuffer.wrap(content);
    final int firstByte = buffer.get() & 0xFF;
    if(firstByte == 1) {
      return decryptIntroductionPointsWithBasicAuth(buffer);
    } else if(firstByte == 2) {
      return decryptIntroductionPointsWithStealthAuth(buffer);
    } else {
      throw new HSAuthenticationException("Introduction points section begins with unrecognized byte ("+ firstByte +")");
    }
  }
 
  private static class BasicAuthEntry {
    final byte[] id;
    final byte[] skey;
    BasicAuthEntry(byte[] id, byte[] skey) {
      this.id = id;
      this.skey = skey;
    }
  }
 
  private BasicAuthEntry createEntry(ByteBuffer bb) {
    final byte[] id = new byte[BASIC_ID_LENGTH];
    final byte[] skey = new byte[TorStreamCipher.KEY_LEN];
    bb.get(id);
    bb.get(skey);
    return new BasicAuthEntry(id, skey);
  }
 
  private byte[] decryptIntroductionPointsWithBasicAuth(ByteBuffer buffer) throws HSAuthenticationException {
    if(cookie == null || cookie.getType() != CookieType.COOKIE_BASIC) {
      throw new TorParsingException("Introduction points encrypted with 'basic' authentication and no cookie available to decrypt");
    }

    final List<BasicAuthEntry> entries = readBasicEntries(buffer);
    final byte[] iv = readAuthIV(buffer);
    final byte[] id = generateAuthId(iv);
    final byte[] k = findKeyInAuthEntries(entries, id);

    return decryptRemaining(buffer, k, iv);
  }
 
  private List<BasicAuthEntry> readBasicEntries(ByteBuffer b) {
    final int blockCount = b.get() & 0xFF;
    final int entryCount = blockCount * 16;
    final List<BasicAuthEntry> entries = new ArrayList<BasicAuthEntry>(entryCount);
    for(int i = 0; i < entryCount; i++) {
      entries.add( createEntry(b) );
    }
    return entries;
  }
 
 
  private byte[] readAuthIV(ByteBuffer b) {
    final byte[] iv = new byte[16];
    b.get(iv);
    return iv;
  }

  private byte[] generateAuthId(byte[] iv) {
    final TorMessageDigest md = new TorMessageDigest();
    md.update(cookie.getValue());
    md.update(iv);
    final byte[] digest = md.getDigestBytes();
    final byte[] id = new byte[BASIC_ID_LENGTH];
    System.arraycopy(digest, 0, id, 0, BASIC_ID_LENGTH);
    return id;
  }

  private byte[] findKeyInAuthEntries(List<BasicAuthEntry> entries, byte[] id) throws HSAuthenticationException {
    for(BasicAuthEntry e: entries) {
      if(Arrays.equals(id, e.id)) {
        return decryptAuthEntry(e);
      }
    }
    throw new HSAuthenticationException("Could not find matching cookie id for basic authentication");
  }
 
  private byte[] decryptAuthEntry(BasicAuthEntry entry) throws HSAuthenticationException {
    TorStreamCipher cipher = TorStreamCipher.createFromKeyBytes(cookie.getValue());
    cipher.encrypt(entry.skey);
    return entry.skey;
  }
 
  private byte[] decryptRemaining(ByteBuffer buffer, byte[] key, byte[] iv) {
    TorStreamCipher streamCipher = TorStreamCipher.createFromKeyBytesWithIV(key, iv);
    final byte[] remaining = new byte[buffer.remaining()];
    buffer.get(remaining);
    streamCipher.encrypt(remaining);
    return remaining;
  }
 
  private byte[] decryptIntroductionPointsWithStealthAuth(ByteBuffer buffer) {
    if(cookie == null || cookie.getType() != CookieType.COOKIE_STEALTH) {
      throw new TorParsingException("Introduction points encrypted with 'stealth' authentication and no cookie available to descrypt");
    }
    final byte[] iv = readAuthIV(buffer);
    return decryptRemaining(buffer, cookie.getValue(), iv);
  }
}
TOP

Related Classes of com.subgraph.orchid.circuits.hs.HSAuthentication$BasicAuthEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.