From 4e749965f22bae822510d33ee5f894107aba9b3d Mon Sep 17 00:00:00 2001
From: Daniel Huigens <d.huigens@protonmail.com>
Date: Mon, 18 Jun 2018 14:12:45 +0200
Subject: [PATCH] Remove support for V3 keys and signatures

---
 src/key.js                |  46 +++++--------
 src/packet/public_key.js  |  23 +------
 src/packet/signature.js   | 139 +++++++++++---------------------------
 test/general/key.js       |  42 +-----------
 test/general/signature.js |  99 ---------------------------
 5 files changed, 58 insertions(+), 291 deletions(-)

diff --git a/src/key.js b/src/key.js
index 661c8f13..8465b836 100644
--- a/src/key.js
+++ b/src/key.js
@@ -337,7 +337,6 @@ Key.prototype.getEncryptionKey = async function(keyId, date=new Date(), userId={
   const primaryKey = this.keyPacket;
   if (await this.verifyPrimaryKey(date, userId) === enums.keyStatus.valid) {
     // V4: by convention subkeys are preferred for encryption service
-    // V3: keys MUST NOT have subkeys
     const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created);
     for (let i = 0; i < subKeys.length; i++) {
       if (!keyId || subKeys[i].getKeyId().equals(keyId)) {
@@ -477,28 +476,23 @@ Key.prototype.verifyPrimaryKey = async function(date=new Date(), userId={}) {
  * @async
  */
 Key.prototype.getExpirationTime = async function(capabilities, keyId, userId) {
-  if (this.keyPacket.version === 3) {
-    return getExpirationTime(this.keyPacket);
+  const primaryUser = await this.getPrimaryUser(null);
+  if (!primaryUser) {
+    throw new Error('Could not find primary user');
   }
-  if (this.keyPacket.version >= 4) {
-    const primaryUser = await this.getPrimaryUser(null);
-    if (!primaryUser) {
-      throw new Error('Could not find primary user');
-    }
-    const selfCert = primaryUser.selfCertification;
-    const keyExpiry = getExpirationTime(this.keyPacket, selfCert);
-    const sigExpiry = selfCert.getExpirationTime();
-    let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry;
-    if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') {
-      const encryptExpiry = (await this.getEncryptionKey(keyId, null, userId)).getExpirationTime();
-      if (encryptExpiry < expiry) expiry = encryptExpiry;
-    }
-    if (capabilities === 'sign' || capabilities === 'encrypt_sign') {
-      const signExpiry = (await this.getSigningKey(keyId, null, userId)).getExpirationTime();
-      if (signExpiry < expiry) expiry = signExpiry;
-    }
-    return expiry;
+  const selfCert = primaryUser.selfCertification;
+  const keyExpiry = getExpirationTime(this.keyPacket, selfCert);
+  const sigExpiry = selfCert.getExpirationTime();
+  let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry;
+  if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') {
+    const encryptExpiry = (await this.getEncryptionKey(keyId, null, userId)).getExpirationTime();
+    if (encryptExpiry < expiry) expiry = encryptExpiry;
   }
+  if (capabilities === 'sign' || capabilities === 'encrypt_sign') {
+    const signExpiry = (await this.getSigningKey(keyId, null, userId)).getExpirationTime();
+    if (signExpiry < expiry) expiry = signExpiry;
+  }
+  return expiry;
 };
 
 /**
@@ -1075,10 +1069,6 @@ SubKey.prototype.isRevoked = async function(primaryKey, signature, key, date=new
 SubKey.prototype.verify = async function(primaryKey, date=new Date()) {
   const that = this;
   const dataToVerify = { key: primaryKey, bind: this.keyPacket };
-  // check for V3 expiration time
-  if (this.keyPacket.version === 3 && isDataExpired(this.keyPacket, null, date)) {
-    return enums.keyStatus.expired;
-  }
   // check subkey binding signatures
   const bindingSignature = getLatestSignature(this.bindingSignatures, date);
   // check binding signature is verified
@@ -1557,12 +1547,8 @@ function isDataExpired(keyPacket, signature, date=new Date()) {
 
 function getExpirationTime(keyPacket, signature) {
   let expirationTime;
-  // check V3 expiration time
-  if (keyPacket.version === 3 && keyPacket.expirationTimeV3 !== 0) {
-    expirationTime = keyPacket.created.getTime() + keyPacket.expirationTimeV3*24*3600*1000;
-  }
   // check V4 expiration time
-  if (keyPacket.version >= 4 && signature.keyNeverExpires === false) {
+  if (signature.keyNeverExpires === false) {
     expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime*1000;
   }
   return expirationTime ? new Date(expirationTime) : Infinity;
diff --git a/src/packet/public_key.js b/src/packet/public_key.js
index f1a07891..927f7e04 100644
--- a/src/packet/public_key.js
+++ b/src/packet/public_key.js
@@ -93,18 +93,11 @@ PublicKey.prototype.read = function (bytes) {
   // A one-octet version number (3, 4 or 5).
   this.version = bytes[pos++];
 
-  if (this.version === 3 || this.version === 4 || this.version === 5) {
+  if (this.version === 4 || this.version === 5) {
     // - A four-octet number denoting the time that the key was created.
     this.created = util.readDate(bytes.subarray(pos, pos + 4));
     pos += 4;
 
-    if (this.version === 3) {
-      // - A two-octet number denoting the time in days that this key is
-      //   valid.  If this number is zero, then it does not expire.
-      this.expirationTimeV3 = util.readNumber(bytes.subarray(pos, pos + 2));
-      pos += 2;
-    }
-
     // - A one-octet number denoting the public-key algorithm of this key.
     this.algorithm = enums.read(enums.publicKey, bytes[pos++]);
     const algo = enums.write(enums.publicKey, this.algorithm);
@@ -147,9 +140,6 @@ PublicKey.prototype.write = function () {
   // Version
   arr.push(new Uint8Array([this.version]));
   arr.push(util.writeDate(this.created));
-  if (this.version === 3) {
-    arr.push(util.writeNumber(this.expirationTimeV3, 2));
-  }
   // A one-octet number denoting the public-key algorithm of this key
   const algo = enums.write(enums.publicKey, this.algorithm);
   arr.push(new Uint8Array([algo]));
@@ -209,9 +199,6 @@ PublicKey.prototype.getKeyId = function () {
     this.keyid.read(util.hex_to_Uint8Array(this.getFingerprint()).subarray(0, 8));
   } else if (this.version === 4) {
     this.keyid.read(util.hex_to_Uint8Array(this.getFingerprint()).subarray(12, 20));
-  } else if (this.version === 3) {
-    const arr = this.params[0].write();
-    this.keyid.read(arr.subarray(arr.length - 8, arr.length));
   }
   return this.keyid;
 };
@@ -232,14 +219,6 @@ PublicKey.prototype.getFingerprintBytes = function () {
   } else if (this.version === 4) {
     toHash = this.writeOld();
     this.fingerprint = crypto.hash.sha1(toHash);
-  } else if (this.version === 3) {
-    const algo = enums.write(enums.publicKey, this.algorithm);
-    const paramCount = crypto.getPubKeyParamTypes(algo).length;
-    toHash = '';
-    for (let i = 0; i < paramCount; i++) {
-      toHash += this.params[i].toString();
-    }
-    this.fingerprint = crypto.hash.md5(util.str_to_Uint8Array(toHash));
   }
   return this.fingerprint;
 };
diff --git a/src/packet/signature.js b/src/packet/signature.js
index e6aada70..c447ba28 100644
--- a/src/packet/signature.js
+++ b/src/packet/signature.js
@@ -105,6 +105,10 @@ Signature.prototype.read = function (bytes) {
   let i = 0;
   this.version = bytes[i++];
 
+  if (this.version !== 4) {
+    throw new Error('Version ' + this.version + ' of the signature is unsupported.');
+  }
+
   const subpackets = bytes => {
     // Two-octet scalar octet count for following subpacket data.
     const subpacket_length = util.readNumber(bytes.subarray(0, 2));
@@ -124,59 +128,25 @@ Signature.prototype.read = function (bytes) {
     return i;
   };
 
-  // switch on version (3 and 4)
-  switch (this.version) {
-    case 3:
-      // One-octet length of following hashed material. MUST be 5.
-      if (bytes[i++] !== 5) {
-        util.print_debug("packet/signature.js\n" +
-          'invalid One-octet length of following hashed material.' +
-          'MUST be 5. @:' + (i - 1));
-      }
+  this.signatureType = bytes[i++];
+  this.publicKeyAlgorithm = bytes[i++];
+  this.hashAlgorithm = bytes[i++];
 
-      // One-octet signature type.
-      this.signatureType = bytes[i++];
+  // hashed subpackets
+  i += subpackets(bytes.subarray(i, bytes.length), true);
 
-      // Four-octet creation time.
-      this.created = util.readDate(bytes.subarray(i, i + 4));
-      i += 4;
+  // A V4 signature hashes the packet body
+  // starting from its first field, the version number, through the end
+  // of the hashed subpacket data.  Thus, the fields hashed are the
+  // signature version, the signature type, the public-key algorithm, the
+  // hash algorithm, the hashed subpacket length, and the hashed
+  // subpacket body.
+  this.signatureData = bytes.subarray(0, i);
+  const sigDataLength = i;
 
-      // Eight-octet Key ID of signer.
-      this.issuerKeyId.read(bytes.subarray(i, i + 8));
-      i += 8;
-
-      // One-octet public-key algorithm.
-      this.publicKeyAlgorithm = bytes[i++];
-
-      // One-octet hash algorithm.
-      this.hashAlgorithm = bytes[i++];
-      break;
-    case 4: {
-      this.signatureType = bytes[i++];
-      this.publicKeyAlgorithm = bytes[i++];
-      this.hashAlgorithm = bytes[i++];
-
-      // hashed subpackets
-      i += subpackets(bytes.subarray(i, bytes.length), true);
-
-      // A V4 signature hashes the packet body
-      // starting from its first field, the version number, through the end
-      // of the hashed subpacket data.  Thus, the fields hashed are the
-      // signature version, the signature type, the public-key algorithm, the
-      // hash algorithm, the hashed subpacket length, and the hashed
-      // subpacket body.
-      this.signatureData = bytes.subarray(0, i);
-      const sigDataLength = i;
-
-      // unhashed subpackets
-      i += subpackets(bytes.subarray(i, bytes.length), false);
-      this.unhashedSubpackets = bytes.subarray(sigDataLength, i);
-
-      break;
-    }
-    default:
-      throw new Error('Version ' + this.version + ' of the signature is unsupported.');
-  }
+  // unhashed subpackets
+  i += subpackets(bytes.subarray(i, bytes.length), false);
+  this.unhashedSubpackets = bytes.subarray(sigDataLength, i);
 
   // Two-octet field holding left 16 bits of signed hash value.
   this.signedHashValue = bytes.subarray(i, i + 2);
@@ -187,22 +157,8 @@ Signature.prototype.read = function (bytes) {
 
 Signature.prototype.write = function () {
   const arr = [];
-  switch (this.version) {
-    case 3:
-      arr.push(new Uint8Array([3, 5])); // version, One-octet length of following hashed material.  MUST be 5
-      arr.push(new Uint8Array([this.signatureType]));
-      arr.push(util.writeDate(this.created));
-      arr.push(this.issuerKeyId.write());
-      arr.push(new Uint8Array([
-        enums.write(enums.publicKey, this.publicKeyAlgorithm),
-        enums.write(enums.hash, this.hashAlgorithm)
-      ]));
-      break;
-    case 4:
-      arr.push(this.signatureData);
-      arr.push(this.unhashedSubpackets ? this.unhashedSubpackets : util.writeNumber(0, 2));
-      break;
-  }
+  arr.push(this.signatureData);
+  arr.push(this.unhashedSubpackets ? this.unhashedSubpackets : util.writeNumber(0, 2));
   arr.push(this.signedHashValue);
   arr.push(this.signature);
   return util.concat(arr);
@@ -220,24 +176,22 @@ Signature.prototype.sign = async function (key, data) {
   const publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm);
   const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
 
-  if (this.version === 4) {
-    const arr = [new Uint8Array([4, signatureType, publicKeyAlgorithm, hashAlgorithm])];
+  const arr = [new Uint8Array([4, signatureType, publicKeyAlgorithm, hashAlgorithm])];
 
-    if (key.version === 5) {
-      // We could also generate this subpacket for version 4 keys, but for
-      // now we don't.
-      this.issuerKeyVersion = key.version;
-      this.issuerFingerprint = key.getFingerprintBytes();
-    }
-
-    this.issuerKeyId = key.getKeyId();
-
-    // Add hashed subpackets
-    arr.push(this.write_all_sub_packets());
-
-    this.signatureData = util.concat(arr);
+  if (key.version === 5) {
+    // We could also generate this subpacket for version 4 keys, but for
+    // now we don't.
+    this.issuerKeyVersion = key.version;
+    this.issuerFingerprint = key.getFingerprintBytes();
   }
 
+  this.issuerKeyId = key.getKeyId();
+
+  // Add hashed subpackets
+  arr.push(this.write_all_sub_packets());
+
+  this.signatureData = util.concat(arr);
+
   const toHash = this.toHash(data);
   const hash = this.hash(data, toHash);
 
@@ -596,16 +550,10 @@ Signature.prototype.toSign = function (type, data) {
 
       const bytes = packet.write();
 
-      if (this.version === 4) {
-        return util.concat([this.toSign(t.key, data),
-          new Uint8Array([tag]),
-          util.writeNumber(bytes.length, 4),
-          bytes]);
-      } else if (this.version === 3) {
-        return util.concat([this.toSign(t.key, data),
-          bytes]);
-      }
-      break;
+      return util.concat([this.toSign(t.key, data),
+        new Uint8Array([tag]),
+        util.writeNumber(bytes.length, 4),
+        bytes]);
     }
     case t.subkey_binding:
     case t.subkey_revocation:
@@ -648,14 +596,7 @@ Signature.prototype.toHash = function(data) {
 
   const bytes = this.toSign(signatureType, data);
 
-  switch (this.version) {
-    case 3:
-      return util.concat([bytes, new Uint8Array([signatureType]), util.writeDate(this.created)]);
-    case 4:
-      return util.concat([bytes, this.signatureData, this.calculateTrailer()]);
-    default:
-      throw new Error('Version ' + this.version + ' of the signature is unsupported.');
-  }
+  return util.concat([bytes, this.signatureData, this.calculateTrailer()]);
 };
 
 Signature.prototype.hash = function(data, toHash, asStream=true) {
diff --git a/test/general/key.js b/test/general/key.js
index 7d2cbf05..61632ce2 100644
--- a/test/general/key.js
+++ b/test/general/key.js
@@ -348,35 +348,6 @@ zoGJ6s48HcP591pN93uAitCcYcinY2ZslmdiCXw+zbeoX4spNrV4T4CYxBjNQdIa
       '=OqO3',
       '-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
 
-  const pub_v3 =
-      ['-----BEGIN PGP PUBLIC KEY BLOCK-----',
-      'Version: SKS 1.1.3',
-      '',
-      'mQENAy9J/w4AAAEIALBDDD4vWqG/Jg59ghhMYAa+E7ECCTv2At8hxsM5cMP8P9sMLjs+GMfD',
-      'IdQSOqlQXbunYADvM1l/h2fOuUMoYFIIGaUsO5Daxvd9uWceM4DVzhXMeJZb9wc5jEJEF21+',
-      'qidKj5OGsMyTrg++mn4Gh/aFXvvy3N3KWaQpPfNi3NRZUpNLz0IlfbXVBQGD6reLoxPptJun',
-      'NqpClyRiesgq8HCscmB2oQo+b9KzSSgzU9qQJA4SljMYVmJ2sDE/sjREI8iKL8lIgUMhJG9q',
-      'NggWjuxFTpVcGKkuQFJIvdL+UhTVvEBuqw6n4cmFAzfZ/AInJM032qLtsaIf5begFKI3up0A',
-      'BRGJARUDBSAxm7HC5begFKI3up0BAbdDB/0TOcI0ec+OPxC5RTZAltgIgyUc0yOjHoTD/yBh',
-      'WjZdQ9YVrLGMWTW4fjhm4rFnppVZKS/N71bwI76SnN9zO4pPfx86aQPR7StmSLJxB+cfh2GL',
-      'gudJoG9ifhJWdNYMUD/yhA0TpJkdHMD5yTDE5Ce/PqKLviiX9C5MPW0AT1MDvafQlzeUXfb5',
-      '1a71vQNPw7W1NBAVZRwztm7TNUaxWMFuOmUtOJpq4F/qDQTIHW2zGPJvl47rpf6JSiyIyU70',
-      'l0deiQcZOXPC80tgInhNoBrz3zbEXhXRJo1fHkr2YSLclpJaoUOHsPxoyrNB28ASL5ZknPwI',
-      'Zx3+cFxaGpRprfSdtCFKb2huIEEuIFBlcnJ5IDxwZXJyeUBwaG9lbml4Lm5ldD6JARUDBRAv',
-      'Sf8k5begFKI3up0BAcbGB/0eLod2qrQxoE2/RUWQtqklOPUj/p/ZTmvZm8BgsdIflb0AMeey',
-      '9o8AbxyAgA3pcrcCjcye79M1Ma2trEvRksvs8hViuq3BXXjDbjPZi3wTtKSvbAC022OV52Sb',
-      '8/sgiTGp7xC8QMqS8w4ZeKoxJGh1TVMYrevUA8a2Rr5aDqrR3EA4rifSHwkVjJWOPF69xiKt',
-      'IVA0LcYJvGsPOQCf2ag+nOcnDrF4dvcmg6XZ/RyLepve+1qkhXsA/oq+yHoaqWfe+bwgssk/',
-      'qw1aEUk7Di8x7vY+cfjvWaazcYGw8kkIwSSqqIq0pkKFz2xDDfSaDJl6OW/2GUK0wDpJmYZo',
-      'PN40iJUDBRAvSgDsU5OkROGu2G8BAeUqBACbC45t4+wYxWCxxp81pkFRb8RWBvEvbXI+Spwd',
-      '4NcKs8jc5OVC8V02yiq4KbKFDRxdw2OWpUCSRAJe1gjsfFrZ+2RivpKk06kbAYthES03MjXg',
-      'cfcV3z2d7IWanJzdcOlzsHzPe1+RoUAaqBjvcqPRCGRlk0ogkYHyWYxElc6574iVAwUQL9iL',
-      'CXr7ES8bepftAQGPywP/d9GSpEmS7LLIqazl4rgN1nkXN5KqduiH8Whu3xcBrdOAn7IYnGTp',
-      'O+Ag4qwKKH+y/ke9CeZL6AnrU9c0pux150dHsDeHtpTPyInkjgKI7BofprydvpiFNd0nlAi4',
-      'J4SAEYr3q92Qn/IiKpnLgo6Ls/GFb7q6y1O/2LL8PC2zrYU=',
-      '=eoGb',
-      '-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
-
   const pub_sig_test =
    ['-----BEGIN PGP PUBLIC KEY BLOCK-----',
     'Version: GnuPG v2.0.19 (GNU/Linux)',
@@ -1328,7 +1299,7 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
     expect(key).to.exist;
   });
 
-  it('Testing key ID and fingerprint for V3 and V4 keys', async function() {
+  it('Testing key ID and fingerprint for V4 keys', async function() {
     const pubKeysV4 = await openpgp.key.readArmored(twoKeys);
     expect(pubKeysV4).to.exist;
     expect(pubKeysV4.err).to.not.exist;
@@ -1337,19 +1308,8 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU=
     const pubKeyV4 = pubKeysV4.keys[0];
     expect(pubKeyV4).to.exist;
 
-    const pubKeysV3 = await openpgp.key.readArmored(pub_v3);
-
-    expect(pubKeysV3).to.exist;
-    expect(pubKeysV3.err).to.not.exist;
-    expect(pubKeysV3.keys).to.have.length(1);
-
-    const pubKeyV3 = pubKeysV3.keys[0];
-    expect(pubKeyV3).to.exist;
-
     expect(pubKeyV4.getKeyId().toHex()).to.equal('4a63613a4d6e4094');
     expect(pubKeyV4.getFingerprint()).to.equal('f470e50dcb1ad5f1e64e08644a63613a4d6e4094');
-    expect(pubKeyV3.getKeyId().toHex()).to.equal('e5b7a014a237ba9d');
-    expect(pubKeyV3.getFingerprint()).to.equal('a44fcee620436a443bc4913640ab3e49');
   });
 
   it('Create new key ID with fromId()', async function() {
diff --git a/test/general/signature.js b/test/general/signature.js
index ba6ecddc..55fc4eac 100644
--- a/test/general/signature.js
+++ b/test/general/signature.js
@@ -220,35 +220,6 @@ describe("Signature", function() {
       '=ok+o',
       '-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
 
-  const pub_v3 =
-    ['-----BEGIN PGP PUBLIC KEY BLOCK-----',
-      'Version: SKS 1.1.3',
-      '',
-      'mQENAy9J/w4AAAEIALBDDD4vWqG/Jg59ghhMYAa+E7ECCTv2At8hxsM5cMP8P9sMLjs+GMfD',
-      'IdQSOqlQXbunYADvM1l/h2fOuUMoYFIIGaUsO5Daxvd9uWceM4DVzhXMeJZb9wc5jEJEF21+',
-      'qidKj5OGsMyTrg++mn4Gh/aFXvvy3N3KWaQpPfNi3NRZUpNLz0IlfbXVBQGD6reLoxPptJun',
-      'NqpClyRiesgq8HCscmB2oQo+b9KzSSgzU9qQJA4SljMYVmJ2sDE/sjREI8iKL8lIgUMhJG9q',
-      'NggWjuxFTpVcGKkuQFJIvdL+UhTVvEBuqw6n4cmFAzfZ/AInJM032qLtsaIf5begFKI3up0A',
-      'BRGJARUDBSAxm7HC5begFKI3up0BAbdDB/0TOcI0ec+OPxC5RTZAltgIgyUc0yOjHoTD/yBh',
-      'WjZdQ9YVrLGMWTW4fjhm4rFnppVZKS/N71bwI76SnN9zO4pPfx86aQPR7StmSLJxB+cfh2GL',
-      'gudJoG9ifhJWdNYMUD/yhA0TpJkdHMD5yTDE5Ce/PqKLviiX9C5MPW0AT1MDvafQlzeUXfb5',
-      '1a71vQNPw7W1NBAVZRwztm7TNUaxWMFuOmUtOJpq4F/qDQTIHW2zGPJvl47rpf6JSiyIyU70',
-      'l0deiQcZOXPC80tgInhNoBrz3zbEXhXRJo1fHkr2YSLclpJaoUOHsPxoyrNB28ASL5ZknPwI',
-      'Zx3+cFxaGpRprfSdtCFKb2huIEEuIFBlcnJ5IDxwZXJyeUBwaG9lbml4Lm5ldD6JARUDBRAv',
-      'Sf8k5begFKI3up0BAcbGB/0eLod2qrQxoE2/RUWQtqklOPUj/p/ZTmvZm8BgsdIflb0AMeey',
-      '9o8AbxyAgA3pcrcCjcye79M1Ma2trEvRksvs8hViuq3BXXjDbjPZi3wTtKSvbAC022OV52Sb',
-      '8/sgiTGp7xC8QMqS8w4ZeKoxJGh1TVMYrevUA8a2Rr5aDqrR3EA4rifSHwkVjJWOPF69xiKt',
-      'IVA0LcYJvGsPOQCf2ag+nOcnDrF4dvcmg6XZ/RyLepve+1qkhXsA/oq+yHoaqWfe+bwgssk/',
-      'qw1aEUk7Di8x7vY+cfjvWaazcYGw8kkIwSSqqIq0pkKFz2xDDfSaDJl6OW/2GUK0wDpJmYZo',
-      'PN40iJUDBRAvSgDsU5OkROGu2G8BAeUqBACbC45t4+wYxWCxxp81pkFRb8RWBvEvbXI+Spwd',
-      '4NcKs8jc5OVC8V02yiq4KbKFDRxdw2OWpUCSRAJe1gjsfFrZ+2RivpKk06kbAYthES03MjXg',
-      'cfcV3z2d7IWanJzdcOlzsHzPe1+RoUAaqBjvcqPRCGRlk0ogkYHyWYxElc6574iVAwUQL9iL',
-      'CXr7ES8bepftAQGPywP/d9GSpEmS7LLIqazl4rgN1nkXN5KqduiH8Whu3xcBrdOAn7IYnGTp',
-      'O+Ag4qwKKH+y/ke9CeZL6AnrU9c0pux150dHsDeHtpTPyInkjgKI7BofprydvpiFNd0nlAi4',
-      'J4SAEYr3q92Qn/IiKpnLgo6Ls/GFb7q6y1O/2LL8PC2zrYU=',
-      '=eoGb',
-      '-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
-
   const pub_expired =
     ['-----BEGIN PGP PUBLIC KEY BLOCK-----',
       'Comment: GPGTools - https://gpgtools.org',
@@ -403,29 +374,6 @@ describe("Signature", function() {
     });
   });
 
-  it('Verify V3 signature. Hash: MD5. PK: RSA. Signature Type: 0x01 (text document)', async function() {
-    const signedArmor =
-      ['-----BEGIN PGP MESSAGE-----',
-        'Version: GnuPG v2.0.19 (GNU/Linux)',
-        '',
-        'owGbwMvMyMj4oOW7S46CznTG09YlLCWpFSVBU47xFGfkF5Uo5KYWFyemp/Jy5QGF',
-        'FXIy84DMt1PnvNq69s20LfpvFm5407Lg9fIJvFy8XJ0MU5lZGUFa4eYxxiQz/6+/',
-        'aFt4/6+e76O6s1afLi65emmK9xsdh7Mr60UnT2UN0LwocWnT7t/nOMJubnypvzTu',
-        'aPJyvm9TTpobW/O+P1n2THLS4UCvWt12Oa2lJ04GLwk/bDF1u+8ZpfPCpsxLVzcs',
-        'ZGtbq/f23XxV/jkL47hr3s3Ic4yoZTW4oZO27GYf37TPp9L3VboCAA==',
-        '=pa6B',
-        '-----END PGP MESSAGE-----'].join('\n');
-
-    const sMsg = await openpgp.message.readArmored(signedArmor);
-    const pub_key = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
-    return sMsg.verify([pub_key]).then(verified => {
-      expect(verified).to.exist;
-      expect(verified).to.have.length(1);
-      expect(verified[0].valid).to.be.true;
-      expect(verified[0].signature.packets.length).to.equal(1);
-    });
-  });
-
   it('Verify signature of signed and encrypted message from GPG2 with openpgp.decrypt', async function() {
     const msg_armor =
       ['-----BEGIN PGP MESSAGE-----',
@@ -459,41 +407,6 @@ describe("Signature", function() {
     });
   });
 
-  it('Verify signature of signed and encrypted message from PGP 10.3.0 with openpgp.decrypt', async function() {
-    const msg_armor =
-      ['-----BEGIN PGP MESSAGE-----',
-        'Version: Encryption Desktop 10.3.0 (Build 9307)',
-        'Charset: utf-8',
-        '',
-        'qANQR1DBjAPghPdEbCAslwED/2S4oNvCjO5TdLUMMUuVOQc8fi6c5XIBu7Y09fEX',
-        'Jm/UrkDHVgmPojLGBDF0CYENNZOVrNfpahY7A3r4HPzGucBzCO1uxuUIKjhtNAAM',
-        'mjD939ernjooOZrM6xDuRaX8adG0LSxpNaVJGxXd/EdlmKDJbYDI6aJ5INrUxzAR',
-        'DAqw0sBSAXgRWgiH6IIiAo5y5WFEDEN9sGStaEQT2wd32kX73M4iZuMt/GM2agiB',
-        'sWb7yLcNHiJ/3OnTfDg9+T543kFq9FlwFbwqygO/wm9e/kgMBq0ZsFOfV+GRtXep',
-        '3qNbJsmzGvdqiUHb/+hkdE191jaSVcO/zaMW4N0Vc1IwIEhZ8I9+9bKwusdVhHT5',
-        'MySnhIogv+0Ilag/aY+UiCt+Zcie69T7Eix48fC/VVW5w3INf1T2CMmDm5ZLZFRN',
-        'oyqzb9Vsgu1gS7SCb6qTbnbV9PlSyU4wJB6siX8hz/U0urokT5se3uYRjiV0KbkA',
-        'zl1/r/wCrmwX4Gl9VN9+33cQgYZAlJLsRw8N82GhbVweZS8qwv24GQ==',
-        '=nx90',
-        '-----END PGP MESSAGE-----'].join('\n');
-
-    const plaintext = 'short message\nnext line\n한국어/조선말\n\n';
-    const esMsg = await openpgp.message.readArmored(msg_armor);
-    const pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
-    const privKey = (await openpgp.key.readArmored(priv_key_arm2)).keys[0];
-
-    await Promise.all(esMsg.getEncryptionKeyIds().map(keyId => privKey.decrypt('hello world', keyId)));
-
-    return openpgp.decrypt({ privateKeys: privKey, publicKeys:[pubKey], message:esMsg }).then(function(decrypted) {
-      expect(decrypted.data).to.exist;
-      expect(decrypted.data).to.equal(plaintext);
-      expect(decrypted.signatures).to.have.length(1);
-      expect(decrypted.signatures[0].valid).to.be.true;
-      expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
-    });
-
-  });
-
   it('Verify signed message with two one pass signatures', async function() {
     const msg_armor =
       ['-----BEGIN PGP MESSAGE-----',
@@ -911,11 +824,6 @@ yYDnCgA=
     expect(pubKey.users[0].selfCertifications[0].keyExpirationTime).to.equal(5*365*24*60*60);
   });
 
-  it('Verify V3 certification signature', async function() {
-    const pubKey = (await openpgp.key.readArmored(pub_v3)).keys[0];
-    await expect(pubKey.users[0].selfCertifications[0].verify(pubKey.primaryKey, {key: pubKey.primaryKey, userId: pubKey.users[0].userId})).to.eventually.be.true;
-  });
-
   it('Write unhashed subpackets', async function() {
     let pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
     expect(pubKey.users[0].selfCertifications).to.exist;
@@ -923,13 +831,6 @@ yYDnCgA=
     expect(pubKey.users[0].selfCertifications).to.exist;
   });
 
-  it('Write V3 signatures', async function() {
-    const pubKey = (await openpgp.key.readArmored(pub_v3)).keys[0];
-    const pubKey2 = (await openpgp.key.readArmored(pubKey.armor())).keys[0];
-    expect(pubKey2).to.exist;
-    expect(pubKey.users[0].selfCertifications).to.eql(pubKey2.users[0].selfCertifications);
-  });
-
   it('Write V4 signatures', async function() {
     const pubKey = (await openpgp.key.readArmored(pub_key_arm2)).keys[0];
     const pubKey2 = (await openpgp.key.readArmored(pubKey.armor())).keys[0];