<p>Indeed, if you have a public key and then the hash of another public key, you can build a script that behaves similarly than a 1-of-2 multisig. Something like this would do the trick:</p>

<pre><code>OP_DUP OP_TOALTSTACK &lt;pubKey1&gt; OP_CHECKSIG
OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY 
OP_CHECKSIGVERIFY OP_ENDIF
&lt;0x01&gt;
</code></pre>

<p>The output script will be unlocked if either a signature validated with <code>pubKey1</code> is provided or a valid signature and a public key that match <code>pubKeyHash2</code> are provided.</p>

<p>In the first case, the user with <code>pubKey1</code> spends with a valid signature:</p>

<p><code>ScriptSig: &lt;signature1&gt;</code></p>

<p>Evaluation:</p>

<ol>
<li><code>&lt;signature1&gt; OP_DUP OP_TOALTSTACK &lt;pubKey1&gt; OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature1&gt; &lt;signature1&gt; OP_TOALTSTACK &lt;pubKey1&gt; OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature1&gt; &lt;pubKey1&gt; OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>0x01 OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;0x01&gt;</code></li>
</ol>

<p>Note that since the first <code>OP_CHECKSIG</code> returns <code>True</code>, the opcodes inside the conditional are not executed, and the script terminates succesfully  (leaving <code>0x01</code> in the stack).</p>

<p>In the second case, the user with <code>pubKeyHash2</code> spends with a valid signature and revealing the public key matching the hash:</p>

<p><code>ScriptSig: &lt;signature2&gt; &lt;pubKey2&gt;</code></p>

<p>Evaluation:</p>

<ol>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; OP_DUP OP_TOALTSTACK &lt;pubKey1&gt; OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; &lt;pubKey2&gt; OP_TOALTSTACK &lt;pubKey1&gt; OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; &lt;pubKey1&gt; OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; 0x00 OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; OP_FROMALTSTACK OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; OP_DUP OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; &lt;pubKey2&gt; OP_HASH &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; &lt;pubKeyHash2&gt; &lt;pubKeyHash2&gt; OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;signature2&gt; &lt;pubKey2&gt; OP_CHECKSIGVERIFY OP_ENDIF &lt;0x01&gt;</code></li>
<li><code>&lt;0x01&gt;</code></li>
</ol>

<p>In this case, the first <code>OP_CHECKSIG</code> fails, so the code inside the conditional is executed. This code validates the signature and public key with <code>pubKeyHash2</code>, and makes the script fail if any of the validations fail. If both validations are passed, then the script pushes <code>0x01</code> to the stack, terminating successfully.</p>

<p>PD: Please don't use this script in the mainnet without first having checked that it works as expected ;)</p>

CC BY-SA 3.0
2018-02-15T10:35:40.153Z
Interesting, thank you. One question though, in the first case you have put something on alternative stack and you left it there, is that okay?
Wapac
CC BY-SA 3.0
2018-02-22T12:29:12.963Z
@Wapac Yes, I think so. There does not seem to be any code checking if there is anything left in the alt stack in the script evaluation function (https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L251).
cpsola
CC BY-SA 3.0
2018-02-08T18:09:09.193Z
2018-02-08T18:09:09.193Z
cpsola
<p>I want to construct a 1-of-2 multisig script and I don't know one of the keys, I only know its address. Question is, is that possible?</p>

<p>So I was thinking if it is possible to construct a script that would have 2 branches, first branch would be allowing the first public key which I now to spend the money. And the 2nd branch would need a spending script to provide the public key which would then be duplicated on the stack, then hashed in order to get the address from it, this address would be compared to the address I know and if that matched, it would allow spending the coins.</p>

CC BY-SA 3.0
2018-02-04T22:04:13.733Z
On 2nd branch: do you really mean bitcoin addresses? When hashing a pub key, this is not the address. To come from a public key to an address would require 9 steps (see e.g. here: http://gobittest.appspot.com/Address). So somehow an address would be difficult, cause the stack operators do not allow for the checksum and base58check encoding.
pebwindkraft
CC BY-SA 3.0
2018-02-05T12:16:15.403Z
I am interested in any secure solution, I didn't want to suggest a particular one, so I was more just expressing the way I was thinking about it, which could be wrong.
Wapac
<multi-signature>
multisig without knowing one of the keys
Wapac
# multisig without knowing one of the keys

(Asked by: username_0 on 2018-02-04)

I want to construct a 1-of-2 multisig script and I don't know one of the keys, I only know its address. Question is, is that possible?

So I was thinking if it is possible to construct a script that would have 2 branches, first branch would be allowing the first public key which I now to spend the money. And the 2nd branch would need a spending script to provide the public key which would then be duplicated on the stack, then hashed in order to get the address from it, this address would be compared to the address I know and if that matched, it would allow spending the coins.

**Tags:** multi-signature

> **Comments:**
> **username_1**: On 2nd branch: do you really mean bitcoin addresses? When hashing a pub key, this is not the address. To come from a public key to an address would require 9 steps (see e.g. here: http://gobittest.appspot.com/Address). So somehow an address would be difficult, cause the stack operators do not allow for the checksum and base58check encoding.  
> **username_0**: I am interested in any secure solution, I didn't want to suggest a particular one, so I was more just expressing the way I was thinking about it, which could be wrong.  

---

## 1 answers

### Answer by username_2 on 2018-02-08. Score: 1 | Accepted answer

Indeed, if you have a public key and then the hash of another public key, you can build a script that behaves similarly than a 1-of-2 multisig. Something like this would do the trick:
OP_DUP OP_TOALTSTACK  OP_CHECKSIG
OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY 
OP_CHECKSIGVERIFY OP_ENDIF
<0x01>

The output script will be unlocked if either a signature validated with pubKey1 is provided or a valid signature and a public key that match pubKeyHash2 are provided.
In the first case, the user with pubKey1 spends with a valid signature:
ScriptSig: 
Evaluation:

 OP_DUP OP_TOALTSTACK  OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
  OP_TOALTSTACK  OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
  OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
0x01 OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
<0x01>

Note that since the first OP_CHECKSIG returns True, the opcodes inside the conditional are not executed, and the script terminates succesfully  (leaving 0x01 in the stack).
In the second case, the user with pubKeyHash2 spends with a valid signature and revealing the public key matching the hash:
ScriptSig:  
Evaluation:

  OP_DUP OP_TOALTSTACK  OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
   OP_TOALTSTACK  OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
   OP_CHECKSIG OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
 0x00 OP_NOTIF OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
 OP_FROMALTSTACK OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
  OP_DUP OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
   OP_HASH  OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
    OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_ENDIF <0x01>
  OP_CHECKSIGVERIFY OP_ENDIF <0x01>
<0x01>

In this case, the first OP_CHECKSIG fails, so the code inside the conditional is executed. This code validates the signature and public key with pubKeyHash2, and makes the script fail if any of the validations fail. If both validations are passed, then the script pushes 0x01 to the stack, terminating successfully.
PD: Please don't use this script in the mainnet without first having checked that it works as expected ;)

> **Comments:**
> **username_0**: Interesting, thank you. One question though, in the first case you have put something on alternative stack and you left it there, is that okay?  
> **username_2**: @username_0 Yes, I think so. There does not seem to be any code checking if there is anything left in the alt stack in the script evaluation function (https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L251).  

---

