⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 authgeneric.java

📁 snmp4j 1.8.2版 The org.snmp4j classes are capable of creating, sending, and receiving SNMPv1/v2c/v3
💻 JAVA
字号:
/*_############################################################################
  _## 
  _##  SNMP4J - AuthGeneric.java  
  _## 
  _##  Copyright 2003-2007  Frank Fock and Jochen Katz (SNMP4J.org)
  _##  
  _##  Licensed under the Apache License, Version 2.0 (the "License");
  _##  you may not use this file except in compliance with the License.
  _##  You may obtain a copy of the License at
  _##  
  _##      http://www.apache.org/licenses/LICENSE-2.0
  _##  
  _##  Unless required by applicable law or agreed to in writing, software
  _##  distributed under the License is distributed on an "AS IS" BASIS,
  _##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  _##  See the License for the specific language governing permissions and
  _##  limitations under the License.
  _##  
  _##########################################################################*/





package org.snmp4j.security;

import java.security.MessageDigest;
import org.snmp4j.log.*;
import org.snmp4j.smi.OctetString;

/**
 * The abstract class AuthGeneric implements common operations for
 * SNMP authentication protocols, such as MD5 and SHA.
 *
 * @author Jochen Katz & Frank Fock
 * @version 1.0
 */

public abstract class AuthGeneric
    implements AuthenticationProtocol {

  private static final LogAdapter logger = LogFactory.getLogger(AuthGeneric.class);
  private int digestLength;
  private String protoName;

  public AuthGeneric(String protoName, int digestLength) {
    this.protoName = protoName;
    this.digestLength = digestLength;
  }

  public int getDigestLength() {
    return digestLength;
  }

  /**
   * Get a fresh MessageDigest object of the Algorithm specified in the
   * constructor.
   *
   * @return a new, fresh Message Digest object.
   */
  protected MessageDigest getDigestObject() {
    MessageDigest md;
    try {
      md = MessageDigest.getInstance(protoName);
    }
    catch (java.security.NoSuchAlgorithmException e) {
      throw new InternalError(protoName + " not supported in this VM.");
    }
    // not needed the first time: md.reset();
    return md;
  }

  public boolean authenticate(byte[] authenticationKey,
                              byte[] message,
                              int messageOffset,
                              int messageLength,
                              ByteArrayWindow digest) {
    MessageDigest md = getDigestObject();

    byte[] newDigest;
    byte[] k_ipad = new byte[64]; /* inner padding - key XORd with ipad */
    byte[] k_opad = new byte[64]; /* outer padding - key XORd with opad */

    // clear the bytes for the digest (12 bytes only!)
    for (int i = 0; i < MESSAGE_AUTHENTICATION_CODE_LENGTH; ++i) {
      digest.set(i, (byte)0);
    }

    /*
     * the HMAC_MD transform looks like:
     *
     * MD(K XOR opad, MD(K XOR ipad, msg))
     *
     * where K is an n byte key
     * ipad is the byte 0x36 repeated 64 times
     * opad is the byte 0x5c repeated 64 times
     * and text is the data being protected
     */
    /* start out by storing key, ipad and opad in pads */
    for (int i = 0; i < authenticationKey.length; ++i) {
      k_ipad[i] = (byte) (authenticationKey[i] ^ 0x36);
      k_opad[i] = (byte) (authenticationKey[i] ^ 0x5c);
    }
    for (int i = authenticationKey.length; i < 64; ++i) {
      k_ipad[i] = 0x36;
      k_opad[i] = 0x5c;
    }

    /* perform inner MD */
    md.update(k_ipad); /* start with inner pad      */
    md.update(message, messageOffset, messageLength); /* then text of msg  */
    newDigest = md.digest(); /* finish up 1st pass        */
    /* perform outer MD */
    md.reset(); /* init md5 for 2nd pass     */
    md.update(k_opad); /* start with outer pad      */
    md.update(newDigest); /* then results of 1st hash  */
    newDigest = md.digest(); /* finish up 2nd pass        */

    // copy the digest into the message (12 bytes only!)
    for (int i = 0; i < 12; ++i) {
      digest.set(i, newDigest[i]);
    }
    return true;
  }

  public boolean isAuthentic(byte[] authenticationKey,
                             byte[] message,
                             int messageOffset,
                             int messageLength,
                             ByteArrayWindow digest) {
    // copy digest from message
    ByteArrayWindow origDigest =
        new ByteArrayWindow(new byte[MESSAGE_AUTHENTICATION_CODE_LENGTH], 0,
                            MESSAGE_AUTHENTICATION_CODE_LENGTH);
    System.arraycopy(digest.getValue(), digest.getOffset(),
                     origDigest.getValue(), 0,
                     MESSAGE_AUTHENTICATION_CODE_LENGTH);

    // use the authenticate() method to recalculate the digest
    if (!authenticate(authenticationKey, message, messageOffset,
                      messageLength, digest)) {
      return false;
    }
    return digest.equals(origDigest, 12);
  }

  public byte[] changeDelta(byte[] oldKey,
                            byte[] newKey,
                            byte[] random) {
    // algorithm according to USM-document textual convention KeyChange
    // simplified for fixed length keys

    MessageDigest md5 = getDigestObject();

    if (logger.isDebugEnabled()) {
      logger.debug(protoName + "oldKey: " + new OctetString(oldKey).toHexString());
      logger.debug(protoName + "newKey: " + new OctetString(newKey).toHexString());
      logger.debug(protoName + "random: " + new OctetString(random).toHexString());
    }

    // step 1: initialize temporary variable
    // step 2: nothing to do as we only support fixed length keys ;-)
    // step 3:
    md5.update(oldKey);
    md5.update(random);
    byte[] digest = md5.digest();

    // step 4:
    byte[] keyChange = new byte[random.length + newKey.length];
    for (int i = 0; i < random.length; ++i) {
      keyChange[i] = random[i];
    }
    for (int i = random.length; i < random.length + newKey.length; ++i) {
      keyChange[i] = newKey[i - random.length];
    }
    for (int j = oldKey.length; j < keyChange.length; j++) {
      keyChange[j] ^= digest[j - oldKey.length];
    }

    if (logger.isDebugEnabled()) {
      logger.debug(protoName + "keyChange:" +
                   new OctetString(keyChange).toHexString());
    }

    return keyChange;
  }

  public byte[] passwordToKey(OctetString passwordString, byte[] engineID) {

    MessageDigest md = getDigestObject();

    byte[] digest;
    byte[] buf = new byte[64];
    int password_index = 0;
    int count = 0;
    byte[] password = passwordString.getValue();

    /* Use while loop until we've done 1 Megabyte */
    while (count < 1048576) {
      for (int i = 0; i < 64; ++i) {
        /* Take the next octet of the password, wrapping */
        /* to the beginning of the password as necessary.*/
        buf[i] = password[password_index++ % password.length];
      }
      md.update(buf);
      count += 64;
    }
    digest = md.digest();
    if (logger.isDebugEnabled()) {
      logger.debug(protoName + "First digest: " +
                   new OctetString(digest).toHexString());
    }

    /*****************************************************/
    /* Now localize the key with the engine_id and pass  */
    /* through MD to produce final key                   */
    /*****************************************************/
    md.reset();
    md.update(digest);
    md.update(engineID);
    md.update(digest);
    digest = md.digest();
    if (logger.isDebugEnabled()) {
      logger.debug(protoName + "localized key: " +
                   new OctetString(digest).toHexString());
    }

    return digest;
  }

  public byte[] hash(byte[] data) {
    MessageDigest md = getDigestObject();
    md.update(data);
    return md.digest();
  }

  public byte[] hash(byte[] data, int offset, int length) {
    MessageDigest md = getDigestObject();
    md.update(data, offset, length);
    return md.digest();
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -