|
1 | 1 | import { randomBytes } from '@libp2p/crypto' |
2 | 2 | import { publicKeyFromProtobuf } from '@libp2p/crypto/keys' |
3 | | -import { StrictSign, StrictNoSign, type Message, type PublicKey, type PeerId } from '@libp2p/interface' |
| 3 | +import { type Message, type PublicKey, type PeerId } from '@libp2p/interface' |
4 | 4 | import { peerIdFromMultihash } from '@libp2p/peer-id' |
5 | 5 | import * as Digest from 'multiformats/hashes/digest' |
6 | 6 | import { concat as uint8ArrayConcat } from 'uint8arrays/concat' |
@@ -80,92 +80,84 @@ export async function buildRawMessage ( |
80 | 80 |
|
81 | 81 | export type ValidationResult = { valid: true, message: Message } | { valid: false, error: ValidateError } |
82 | 82 |
|
83 | | -export async function validateToRawMessage ( |
84 | | - signaturePolicy: typeof StrictNoSign | typeof StrictSign, |
| 83 | +export function validateStrictNoSignMessage ( |
| 84 | + msg: RPC.Message |
| 85 | +): ValidationResult { |
| 86 | + if (msg.signature != null) return { valid: false, error: ValidateError.SignaturePresent } |
| 87 | + if (msg.seqno != null) return { valid: false, error: ValidateError.SeqnoPresent } |
| 88 | + if (msg.from != null) return { valid: false, error: ValidateError.FromPresent } |
| 89 | + |
| 90 | + return { valid: true, message: { type: 'unsigned', topic: msg.topic, data: msg.data ?? new Uint8Array(0) } } |
| 91 | +} |
| 92 | + |
| 93 | +export async function validateStrictSignMessage ( |
85 | 94 | msg: RPC.Message |
86 | 95 | ): Promise<ValidationResult> { |
87 | | - // If strict-sign, verify all |
88 | | - // If anonymous (no-sign), ensure no preven |
89 | | - |
90 | | - switch (signaturePolicy) { |
91 | | - case StrictNoSign: |
92 | | - if (msg.signature != null) return { valid: false, error: ValidateError.SignaturePresent } |
93 | | - if (msg.seqno != null) return { valid: false, error: ValidateError.SeqnoPresent } |
94 | | - if (msg.from != null) return { valid: false, error: ValidateError.FromPresent } |
95 | | - |
96 | | - return { valid: true, message: { type: 'unsigned', topic: msg.topic, data: msg.data ?? new Uint8Array(0) } } |
97 | | - |
98 | | - case StrictSign: { |
99 | | - // Verify seqno |
100 | | - if (msg.seqno == null) return { valid: false, error: ValidateError.InvalidSeqno } |
101 | | - if (msg.seqno.length !== 8) { |
102 | | - return { valid: false, error: ValidateError.InvalidSeqno } |
103 | | - } |
| 96 | + // Verify seqno |
| 97 | + if (msg.seqno == null) return { valid: false, error: ValidateError.InvalidSeqno } |
| 98 | + if (msg.seqno.length !== 8) { |
| 99 | + return { valid: false, error: ValidateError.InvalidSeqno } |
| 100 | + } |
104 | 101 |
|
105 | | - if (msg.signature == null) return { valid: false, error: ValidateError.InvalidSignature } |
106 | | - if (msg.from == null) return { valid: false, error: ValidateError.InvalidPeerId } |
| 102 | + if (msg.signature == null) return { valid: false, error: ValidateError.InvalidSignature } |
| 103 | + if (msg.from == null) return { valid: false, error: ValidateError.InvalidPeerId } |
107 | 104 |
|
108 | | - let fromPeerId: PeerId |
109 | | - try { |
110 | | - // TODO: Fix PeerId types |
111 | | - fromPeerId = peerIdFromMultihash(Digest.decode(msg.from)) |
112 | | - } catch (e) { |
113 | | - return { valid: false, error: ValidateError.InvalidPeerId } |
114 | | - } |
| 105 | + let fromPeerId: PeerId |
| 106 | + try { |
| 107 | + // TODO: Fix PeerId types |
| 108 | + fromPeerId = peerIdFromMultihash(Digest.decode(msg.from)) |
| 109 | + } catch (e) { |
| 110 | + return { valid: false, error: ValidateError.InvalidPeerId } |
| 111 | + } |
115 | 112 |
|
116 | | - // - check from defined |
117 | | - // - transform source to PeerId |
118 | | - // - parse signature |
119 | | - // - get .key, else from source |
120 | | - // - check key == source if present |
121 | | - // - verify sig |
122 | | - |
123 | | - let publicKey: PublicKey |
124 | | - if (msg.key != null) { |
125 | | - publicKey = publicKeyFromProtobuf(msg.key) |
126 | | - // TODO: Should `fromPeerId.pubKey` be optional? |
127 | | - if (fromPeerId.publicKey !== undefined && !publicKey.equals(fromPeerId.publicKey)) { |
128 | | - return { valid: false, error: ValidateError.InvalidPeerId } |
129 | | - } |
130 | | - } else { |
131 | | - if (fromPeerId.publicKey == null) { |
132 | | - return { valid: false, error: ValidateError.InvalidPeerId } |
133 | | - } |
134 | | - publicKey = fromPeerId.publicKey |
135 | | - } |
| 113 | + // - check from defined |
| 114 | + // - transform source to PeerId |
| 115 | + // - parse signature |
| 116 | + // - get .key, else from source |
| 117 | + // - check key == source if present |
| 118 | + // - verify sig |
| 119 | + |
| 120 | + let publicKey: PublicKey |
| 121 | + if (msg.key != null) { |
| 122 | + publicKey = publicKeyFromProtobuf(msg.key) |
| 123 | + // TODO: Should `fromPeerId.pubKey` be optional? |
| 124 | + if (fromPeerId.publicKey !== undefined && !publicKey.equals(fromPeerId.publicKey)) { |
| 125 | + return { valid: false, error: ValidateError.InvalidPeerId } |
| 126 | + } |
| 127 | + } else { |
| 128 | + if (fromPeerId.publicKey == null) { |
| 129 | + return { valid: false, error: ValidateError.InvalidPeerId } |
| 130 | + } |
| 131 | + publicKey = fromPeerId.publicKey |
| 132 | + } |
136 | 133 |
|
137 | | - const rpcMsgPreSign: RPC.Message = { |
138 | | - from: msg.from, |
139 | | - data: msg.data, |
140 | | - seqno: msg.seqno, |
141 | | - topic: msg.topic, |
142 | | - signature: undefined, // Exclude signature field for signing |
143 | | - key: undefined // Exclude key field for signing |
144 | | - } |
| 134 | + const rpcMsgPreSign: RPC.Message = { |
| 135 | + from: msg.from, |
| 136 | + data: msg.data, |
| 137 | + seqno: msg.seqno, |
| 138 | + topic: msg.topic, |
| 139 | + signature: undefined, // Exclude signature field for signing |
| 140 | + key: undefined // Exclude key field for signing |
| 141 | + } |
145 | 142 |
|
146 | | - // Get the message in bytes, and prepend with the pubsub prefix |
147 | | - // the signature is over the bytes "libp2p-pubsub:<protobuf-message>" |
148 | | - const bytes = uint8ArrayConcat([SignPrefix, RPC.Message.encode(rpcMsgPreSign)]) |
| 143 | + // Get the message in bytes, and prepend with the pubsub prefix |
| 144 | + // the signature is over the bytes "libp2p-pubsub:<protobuf-message>" |
| 145 | + const bytes = uint8ArrayConcat([SignPrefix, RPC.Message.encode(rpcMsgPreSign)]) |
149 | 146 |
|
150 | | - if (!(await publicKey.verify(bytes, msg.signature))) { |
151 | | - return { valid: false, error: ValidateError.InvalidSignature } |
152 | | - } |
| 147 | + if (!(await publicKey.verify(bytes, msg.signature))) { |
| 148 | + return { valid: false, error: ValidateError.InvalidSignature } |
| 149 | + } |
153 | 150 |
|
154 | | - return { |
155 | | - valid: true, |
156 | | - message: { |
157 | | - type: 'signed', |
158 | | - from: fromPeerId, |
159 | | - data: msg.data ?? new Uint8Array(0), |
160 | | - sequenceNumber: BigInt(`0x${uint8ArrayToString(msg.seqno, 'base16')}`), |
161 | | - topic: msg.topic, |
162 | | - signature: msg.signature, |
163 | | - key: publicKey |
164 | | - } |
165 | | - } |
| 151 | + return { |
| 152 | + valid: true, |
| 153 | + message: { |
| 154 | + type: 'signed', |
| 155 | + from: fromPeerId, |
| 156 | + data: msg.data ?? new Uint8Array(0), |
| 157 | + sequenceNumber: BigInt(`0x${uint8ArrayToString(msg.seqno, 'base16')}`), |
| 158 | + topic: msg.topic, |
| 159 | + signature: msg.signature, |
| 160 | + key: publicKey |
166 | 161 | } |
167 | | - |
168 | | - default: |
169 | | - throw new Error('Unreachable') |
170 | 162 | } |
171 | 163 | } |
0 commit comments