MessageAuthenticator
MessageAuthenticator
https://coova.github.io/JRadius/
https://coova.github.io/JRadius/
import org.tinyradius.packet.RadiusPacket;
import org.tinyradius.util.RadiusUtil;
import java.nio.charset.StandardCharsets;
public class RadiusAuthUtils {
/**
* 生成 RADIUS 报文的 Message-Authenticator 值
* @param sharedSecret 共享密钥
* @param requestAuthenticator 请求认证器(16 字节随机数)
* @param packetBytes 完整的 RADIUS 报文字节数据(包含报文头和属性)
* @return Message-Authenticator 的字节数组(16 字节)
*/
public static byte[] generateMessageAuthenticator(String sharedSecret, byte[] requestAuthenticator, byte[] packetBytes) {
try {
// 1. 使用 HMAC-MD5 计算哈希
byte[] hmacMd5 = RadiusUtil.getMd5Digest(sharedSecret.getBytes(StandardCharsets.UTF_8), packetBytes);
// 2. 提取前 16 字节作为 Message-Authenticator
byte[] messageAuthenticator = new byte[16];
System.arraycopy(hmacMd5, 0, messageAuthenticator, 0, 16);
return messageAuthenticator;
} catch (Exception e) {
throw new RuntimeException("生成 Message-Authenticator 失败", e);
}
}
}
public static byte[] generateMessageAuthenticator(byte[] sharedSecret, RADIUS packet) {
try {
byte[] messageBytes = packet.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(sharedSecret, "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(secretKeySpec);
byte[] macValue = mac.doFinal(messageBytes);
Attribute macAttribute = new MessageAuthenticator(macValue);
List<Attribute> attributes = packet.getAttributes();
attributes.add(macAttribute);
return macValue;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to generate Message-Authenticator", e);
}
}
jradius-1.1.5
package net.jradius.util;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.io.IOException;
import java.nio.ByteBuffer;
import net.jradius.packet.RadiusFormat;
import net.jradius.packet.RadiusPacket;
import net.jradius.packet.attribute.AttributeDictionary;
import net.jradius.packet.attribute.AttributeFactory;
import net.jradius.packet.attribute.RadiusAttribute;
public class MessageAuthenticator
{
private static final RadiusFormat format = RadiusFormat.getInstance();
public static void generateRequestMessageAuthenticator(RadiusPacket request, String sharedSecret) throws IOException, InvalidKeyException, NoSuchAlgorithmException
{
byte[] hash = new byte[16];
ByteBuffer buffer = ByteBuffer.allocate(4096);
request.overwriteAttribute(AttributeFactory.newAttribute(AttributeDictionary.MESSAGE_AUTHENTICATOR, hash, request.isRecyclable()));
format.packPacket(request, sharedSecret, buffer, true);
System.arraycopy(MD5.hmac_md5(buffer.array(), 0, buffer.position(), sharedSecret.getBytes()), 0, hash, 0, 16);
}
public static void generateResponseMessageAuthenticator(RadiusPacket request, RadiusPacket reply, String sharedSecret) throws IOException, InvalidKeyException, NoSuchAlgorithmException
{
byte[] hash = new byte[16];
byte[] requestAuth = request.getAuthenticator();
byte[] replyAuth = reply.getAuthenticator();
ByteBuffer buffer = ByteBuffer.allocate(4096);
reply.setAuthenticator(requestAuth);
reply.overwriteAttribute(AttributeFactory.newAttribute(AttributeDictionary.MESSAGE_AUTHENTICATOR, hash, reply.isRecyclable()));
format.packPacket(reply, sharedSecret, buffer, true);
System.arraycopy(MD5.hmac_md5(buffer.array(), 0, buffer.position(), sharedSecret.getBytes()), 0, hash, 0, 16);
reply.setAuthenticator(replyAuth);
}
public static Boolean verifyRequest(RadiusPacket request, String sharedSecret) throws IOException, InvalidKeyException, NoSuchAlgorithmException
{
byte[] hash = new byte[16];
ByteBuffer buffer = ByteBuffer.allocate(4096);
RadiusAttribute attr = request.findAttribute(AttributeDictionary.MESSAGE_AUTHENTICATOR);
if (attr == null) return null;
byte[] pval = attr.getValue().getBytes();
attr.setValue(hash);
format.packPacket(request, sharedSecret, buffer, true);
System.arraycopy(MD5.hmac_md5(buffer.array(), 0, buffer.position(), sharedSecret.getBytes()), 0, hash, 0, 16);
attr.setValue(pval);
return new Boolean(Arrays.equals(pval, hash));
}
public static Boolean verifyReply(byte[] requestAuth, RadiusPacket reply, String sharedSecret) throws IOException, InvalidKeyException, NoSuchAlgorithmException
{
byte[] replyAuth = reply.getAuthenticator();
byte[] hash = new byte[16];
ByteBuffer buffer = ByteBuffer.allocate(4096);
RadiusAttribute attr = reply.findAttribute(AttributeDictionary.MESSAGE_AUTHENTICATOR);
if (attr == null) return null;
byte[] pval = attr.getValue().getBytes();
attr.setValue(hash);
reply.setAuthenticator(requestAuth);
format.packPacket(reply, sharedSecret, buffer, true);
System.arraycopy(MD5.hmac_md5(buffer.array(), 0, buffer.position(), sharedSecret.getBytes()), 0, hash, 0, 16);
reply.setAuthenticator(replyAuth);
return new Boolean(Arrays.equals(pval, hash));
}
}