001: // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS.security;
004:
005: import java.security.SignatureException;
006: import java.security.interfaces.DSAParams;
007: import java.util.Arrays;
008: import org.xbill.DNS.*;
009:
010: /**
011: * Converts DSA signatures between the RRSIG/SIG record format (as specified
012: * in RFC 2536) and the format used by Java DSA routines (DER-encoded).
013: *
014: * @author Brian Wellington
015: */
016:
017: public class DSASignature {
018:
019: static final int ASN1_SEQ = 0x30;
020: static final int ASN1_INT = 0x2;
021:
022: private DSASignature() {
023: }
024:
025: /**
026: * Converts the signature field in a SIG record to the
027: * format expected by the DSA verification routines.
028: */
029: public static byte[] fromDNS(byte[] sig) {
030: final int len = 20;
031: int n = 0;
032: byte rlen, slen, seqlen;
033:
034: rlen = len;
035: if (sig[1] < 0)
036: rlen++;
037:
038: slen = len;
039: if (sig[len + 1] < 0)
040: slen++;
041:
042: /* 4 = 2 * (INT, value) */
043: seqlen = (byte) (rlen + slen + 4);
044:
045: /* 2 = 1 * (SEQ, value) */
046: byte[] array = new byte[seqlen + 2];
047:
048: array[n++] = ASN1_SEQ;
049: array[n++] = (byte) seqlen;
050: array[n++] = ASN1_INT;
051: array[n++] = rlen;
052: if (rlen > len)
053: array[n++] = 0;
054: for (int i = 0; i < len; i++, n++)
055: array[n] = sig[1 + i];
056: array[n++] = ASN1_INT;
057: array[n++] = slen;
058: if (slen > len)
059: array[n++] = 0;
060: for (int i = 0; i < len; i++, n++)
061: array[n] = sig[1 + len + i];
062: return array;
063: }
064:
065: /**
066: * Converts the signature generated by DSA signature routines to
067: * the one expected inside an RRSIG/SIG record.
068: */
069: public static byte[] toDNS(DSAParams params, byte[] sig)
070: throws SignatureException {
071: int rLength, sLength;
072: int rOffset, sOffset;
073: if ((sig[0] != ASN1_SEQ) || (sig[2] != ASN1_INT))
074: throw new SignatureException("Expected SEQ, INT");
075: rLength = sig[3];
076: rOffset = 4;
077: if (sig[rOffset] == 0) {
078: rLength--;
079: rOffset++;
080: }
081: if (sig[rOffset + rLength] != ASN1_INT)
082: throw new SignatureException("Expected INT");
083: sLength = sig[rOffset + rLength + 1];
084: sOffset = rOffset + rLength + 2;
085: if (sig[sOffset] == 0) {
086: sLength--;
087: sOffset++;
088: }
089:
090: if ((rLength > 20) || (sLength > 20))
091: throw new SignatureException("DSA R/S too long");
092:
093: byte[] newSig = new byte[41];
094: Arrays.fill(newSig, (byte) 0);
095: newSig[0] = (byte) ((params.getP().bitLength() - 512) / 64);
096: System.arraycopy(sig, rOffset, newSig, 1 + (20 - rLength),
097: rLength);
098: System.arraycopy(sig, sOffset, newSig, 21 + (20 - sLength),
099: sLength);
100: return newSig;
101: }
102:
103: }
|